hover on any card to flip it
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