Wednesday, 12 June 2019

django 45 react flippy card with image from django media


hover on any card to flip it


//pages/album

import React, { Component } from 'react';
import '../App.css';
import { Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import { getAlbums } from '../redux/actions/getAlbums';
import { getUsers } from '../redux/actions/getUser';
import FlippyCard from '../partials/flippyCard';
import { Row, Col } from 'reactstrap'

class Albums extends Component {
    constructor(props) {
        super(props);

        this.state = {
            AlbumAuthorData: [],
            AlbumAuthorIntegrated: false,
        };
    }

    componentDidMount() {
        if (this.props.loggedin) {
            this.props.dispatch(getUsers(this.props.token));
        }

        //check every 1 second to see if users are fetched. If so, start fetching Albums
        const waitGetUsers = setInterval(() => {
            if (this.props.gotUsers) {
                this.props.dispatch(getAlbums(this.props.token));
                clearInterval(waitGetUsers);
            }
        }, 1000)

        //check every 1 second to see if albums are fetched. If so, start integrating Albums and Authors
        const waitGetAlbums = setInterval(() => {
            if (this.props.gotAlbums) {
                let newAlbums = []

                this.props.albums.map((album, index) => {
                    const newAlbum = {
                        'id': album.id,
                        'album_title': album.album_title,
                        'artist': album.artist,
                        'genre': album.genre,
                        'date_posted': album.date_posted,
                        'author': this.props.users.filter(author => author.id == album.author)[0].username,
                        'album_logo': album.album_logo
                    }

                    newAlbums.push(newAlbum);
                });

                this.setState({ AlbumAuthorData: newAlbums, AlbumAuthorIntegrated: true });
                clearInterval(waitGetAlbums);
            }
        }, 1000)
    }

    componentDidUpdate() {

    }

    render() {
        if (!this.props.loggedin) {
            return <Redirect to='/login' />
        }

        const cards = [];

        if (this.state.AlbumAuthorIntegrated) {
            this.state.AlbumAuthorData.map((item, index) => {
                const card = <Col key={index}>
                    <FlippyCard data={item}></FlippyCard>
                </Col>

                cards.push(card);
            })
        }

        return (
            <div style={{ marginTop: '20px' }}>
                {this.props.error}

                {
                    this.state.AlbumAuthorIntegrated ?
                        <Row>
                            {cards}
                        </Row>
                        : <p>integrating authors and albums...</p>
                }
            </div>
        );
    }
}

export default connect(
    (store) => {
        return {
            token: store.login.token,
            loggedin: store.login.fetched,
            error: store.albums.error,
            albums: store.albums.albums,
            gotAlbums: store.albums.fetched,
            users: store.users.users,
            gotUsers: store.users.fetched,
        };
    }
)(Albums);

---------------------------------
//partials/flippyCard

import React, { Component } from 'react';
import '../App.css';
import { FaPenNib } from "react-icons/fa";
import { Button } from 'reactstrap';
import { MdEdit, MdDelete } from "react-icons/md";

export default class FlippyCard extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        const imgSrc = 'http://127.0.0.1:8000' + this.props.data.album_logo;

        return (
            <div className="flip-container" style={{ margin: '10px' }}>
                <div className="flipper">
                    <div className="front" style={{ backgroundColor: 'white' }}>
                        <img src={imgSrc}
                            style={{ height: '150px', width: '100%' }}></img>
                        <div style={{ height: '60px' }}>
                            <h6 style={{ textAlign: 'center', marginTop: '10px' }}>{this.props.data.album_title}</h6>
                        </div>
                        <div style={{ backgroundColor: '#F4F6F6', height: '30px', paddingLeft: '5px' }}>
                            <FaPenNib /> <span>{this.props.data.author}</span>
                        </div>
                    </div>
                    <div className="back" style={{ backgroundColor: 'white' }}>
                        <div style={{ textAlign: 'center', height: '220px', paddingTop: '10px' }}>
                            <p>Artist: {this.props.data.artist}</p>
                            <p>Genre: {this.props.data.genre}</p>
                            <div style={{ display: 'flex', justifyContent: 'space-around', marginLeft: '5px', marginRight: '5px' }}>
                                <Button color='primary' size='sm'>View Detail</Button>
                                <Button outline size='sm'><MdEdit /></Button>
                                <Button outline size='sm'><MdDelete /></Button>
                            </div>
                        </div>
                        <div style={{ backgroundColor: '#F4F6F6', height: '30px', paddingLeft: '5px' }}>
                            <FaPenNib /> <span>{this.props.data.date_posted.split('.')[0].replace('T', ' ')}</span>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}

--------------------------------
//app.css

/* entire container, keeps perspective */
.flip-container {
perspective: 1000px;
}
/* flip the pane when hovered */
.flip-container:hover .flipper, .flip-container.hover .flipper {
transform: rotateY(180deg);
}

.flip-container, .front, .back {
width: 200px;
height: 250px;
}

/* flip speed goes here */
.flipper {
transition: 0.6s;
transform-style: preserve-3d;

position: relative;
}

/* hide back of pane during swap */
.front, .back {
backface-visibility: hidden;

position: absolute;
top: 0;
left: 0;
}

/* front pane, placed above back */
.front {
z-index: 2;
/* for firefox 31 */
transform: rotateY(0deg);
}

/* back, initially hidden pane */
.back {
transform: rotateY(180deg);
}

----------------------------------------
//package.json

{
  "name": "python-react",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "antd": "^3.19.1",
    "axios": "^0.19.0",
    "bootstrap": "^4.3.1",
    "querystring": "^0.2.0",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-icons": "^3.7.0",
    "react-redux": "^7.0.3",
    "react-scripts": "3.0.1",
    "react-table": "^6.10.0",
    "reactstrap": "^8.0.0",
    "redux": "^4.0.1",
    "redux-logger": "^3.0.6",
    "redux-promise-middleware": "^6.1.0",
    "redux-thunk": "^2.3.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

reference:
https://mdbootstrap.com/plugins/react/flipping-cards/
https://davidwalsh.name/css-flip
http://chuanshuoge2.blogspot.com/2019/06/django-44-react-redux-chain-actions.html

No comments:

Post a Comment