summaryrefslogtreecommitdiffstats
path: root/front/odiparpack/app/components/Gallery
diff options
context:
space:
mode:
authorDayana31 <[email protected]>2022-04-21 17:27:08 -0500
committerDayana31 <[email protected]>2022-04-21 17:27:08 -0500
commit67c50667678dd0ce4709b29a854f6a47093a1ac5 (patch)
treeb6f9f39092ad54bf6b815984d32b37d7c7ca67ab /front/odiparpack/app/components/Gallery
parent91140b24f0d49a9f89a080ee063e9eb023a4b73a (diff)
parente13e630cd6e4fc0b1ff92098a28a770794c7bb9a (diff)
downloadDP1_project-67c50667678dd0ce4709b29a854f6a47093a1ac5.tar.gz
DP1_project-67c50667678dd0ce4709b29a854f6a47093a1ac5.tar.bz2
DP1_project-67c50667678dd0ce4709b29a854f6a47093a1ac5.zip
Merge branch 'gabshr' into dayana
Diffstat (limited to 'front/odiparpack/app/components/Gallery')
-rw-r--r--front/odiparpack/app/components/Gallery/PhotoGallery.js83
-rw-r--r--front/odiparpack/app/components/Gallery/ProductDetail.js195
-rw-r--r--front/odiparpack/app/components/Gallery/ProductGallery.js152
-rw-r--r--front/odiparpack/app/components/Gallery/photo-jss.js79
-rw-r--r--front/odiparpack/app/components/Gallery/product-jss.js87
5 files changed, 596 insertions, 0 deletions
diff --git a/front/odiparpack/app/components/Gallery/PhotoGallery.js b/front/odiparpack/app/components/Gallery/PhotoGallery.js
new file mode 100644
index 0000000..3877bba
--- /dev/null
+++ b/front/odiparpack/app/components/Gallery/PhotoGallery.js
@@ -0,0 +1,83 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import 'ba-styles/vendors/image-lightbox/image-lightbox.css';
+import { Typography, ButtonBase } from '@material-ui/core';
+import ImageLightbox from '../ImageLightbox/ImageLightbox';
+import styles from './photo-jss';
+
+
+class PhotoGallery extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ photoIndex: 0,
+ isOpen: false,
+ };
+ }
+
+ openPopup = (photoIndex) => {
+ this.setState({ isOpen: true, photoIndex });
+ }
+
+ render() {
+ const { photoIndex, isOpen } = this.state;
+ const { classes, imgData } = this.props;
+ return (
+ <div>
+ {isOpen && (
+ <ImageLightbox
+ mainSrc={imgData[photoIndex].img}
+ nextSrc={imgData[(photoIndex + 1) % imgData.length].img}
+ prevSrc={imgData[(photoIndex + (imgData.length - 1)) % imgData.length].img}
+ onCloseRequest={() => this.setState({ isOpen: false })}
+ onMovePrevRequest={() => this.setState({
+ photoIndex: (photoIndex + (imgData.length - 1)) % imgData.length,
+ })
+ }
+ onMoveNextRequest={() => this.setState({
+ photoIndex: (photoIndex + 1) % imgData.length,
+ })
+ }
+ />
+ )}
+ <div className={classes.masonry}>
+ {
+ imgData.map((thumb, index) => (
+ <figure className={classes.item} key={index.toString()}>
+ <ButtonBase
+ focusRipple
+ className={classes.image}
+ focusVisibleClassName={classes.focusVisible}
+ onClick={() => this.openPopup(index)}
+ >
+ <img src={thumb.img} alt={thumb.title} />
+ <span className={classes.imageBackdrop} />
+ <span className={classes.imageButton}>
+ <Typography
+ component="span"
+ variant="subtitle1"
+ color="inherit"
+ className={classes.imageTitle}
+ >
+ {thumb.title}
+ <span className={classes.imageMarked} />
+ </Typography>
+ </span>
+ </ButtonBase>
+ </figure>
+ ))
+ }
+ </div>
+ </div>
+ );
+ }
+}
+
+PhotoGallery.propTypes = {
+ classes: PropTypes.object.isRequired,
+ imgData: PropTypes.array.isRequired
+};
+
+export default withStyles(styles)(PhotoGallery);
diff --git a/front/odiparpack/app/components/Gallery/ProductDetail.js b/front/odiparpack/app/components/Gallery/ProductDetail.js
new file mode 100644
index 0000000..f05852f
--- /dev/null
+++ b/front/odiparpack/app/components/Gallery/ProductDetail.js
@@ -0,0 +1,195 @@
+import React, { Fragment } from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import Slider from 'react-slick';
+import CloseIcon from '@material-ui/icons/Close';
+import AddShoppingCart from '@material-ui/icons/AddShoppingCart';
+import imgData from 'ba-api/imgData';
+import Type from 'ba-styles/Typography.scss';
+import 'ba-styles/vendors/slick-carousel/slick-carousel.css';
+import 'ba-styles/vendors/slick-carousel/slick.css';
+import 'ba-styles/vendors/slick-carousel/slick-theme.css';
+import {
+ Typography,
+ Grid,
+ Dialog,
+ AppBar,
+ Toolbar,
+ IconButton,
+ Slide,
+ Button,
+ Chip,
+ TextField,
+} from '@material-ui/core';
+import Rating from '../Rating/Rating';
+import styles from './product-jss';
+
+const getThumb = imgData.map(a => a.thumb);
+
+const Transition = React.forwardRef(function Transition(props, ref) { // eslint-disable-line
+ return <Slide direction="up" ref={ref} {...props} />;
+});
+
+class ProductDetail extends React.Component {
+ state = {
+ qty: 1,
+ }
+
+ handleQtyChange = event => {
+ this.setState({ qty: event.target.value });
+ }
+
+ submitToCart = itemAttr => {
+ this.props.handleAddToCart(itemAttr);
+ this.props.close();
+ }
+
+ render() {
+ const {
+ classes,
+ open,
+ close,
+ detailContent,
+ productIndex
+ } = this.props;
+
+ const { qty } = this.state;
+
+ const itemAttr = (item) => {
+ if (item !== undefined) {
+ return {
+ id: detailContent.getIn([productIndex, 'id']),
+ name: detailContent.getIn([productIndex, 'name']),
+ thumbnail: detailContent.getIn([productIndex, 'thumbnail']),
+ price: detailContent.getIn([productIndex, 'price']),
+ quantity: qty
+ };
+ }
+ return false;
+ };
+
+ const settings = {
+ customPaging: (i) => (
+ <a>
+ <img src={getThumb[i]} alt="thumb" />
+ </a>
+ ),
+ infinite: true,
+ dots: true,
+ slidesToShow: 1,
+ slidesToScroll: 1,
+ };
+
+ return (
+ <Dialog
+ fullScreen
+ open={open}
+ onClose={close}
+ TransitionComponent={Transition}
+ >
+ <AppBar className={classes.appBar}>
+ <Toolbar>
+ <Typography variant="h6" color="inherit" className={classes.flex}>
+ {detailContent.getIn([productIndex, 'name'])}
+ </Typography>
+ <IconButton color="inherit" onClick={() => close()} aria-label="Close">
+ <CloseIcon />
+ </IconButton>
+ </Toolbar>
+ </AppBar>
+ <div className={classes.detailContainer}>
+ <Grid container className={classes.root} spacing={3}>
+ <Grid item md={5} sm={12} xs={12}>
+ <div className="container thumb-nav">
+ <Slider {...settings}>
+ {imgData.map((item, index) => {
+ if (index >= 5) {
+ return false;
+ }
+ return (
+ <div key={index.toString()} className={classes.item}>
+ <img src={item.img} alt={item.title} />
+ </div>
+ );
+ })}
+ </Slider>
+ </div>
+ </Grid>
+ <Grid item md={7} sm={12} xs={12}>
+ <section className={classes.detailWrap}>
+ <Typography noWrap gutterBottom variant="h5" className={classes.title} component="h2">
+ {detailContent.getIn([productIndex, 'name'])}
+ </Typography>
+ <div className={classes.price}>
+ <Typography variant="h5">
+ <span>
+$
+ {detailContent.getIn([productIndex, 'price'])}
+ </span>
+ </Typography>
+ {detailContent.getIn([productIndex, 'discount']) !== '' && (
+ <Fragment>
+ <Typography variant="caption" component="h5">
+ <span className={Type.lineThrought}>
+$
+ {detailContent.getIn([productIndex, 'prevPrice'])}
+ </span>
+ </Typography>
+ <Chip label={'Discount ' + detailContent.getIn([productIndex, 'discount'])} className={classes.chipDiscount} />
+ </Fragment>
+ )}
+ {detailContent.getIn([productIndex, 'soldout']) && (
+ <Chip label="Sold Out" className={classes.chipSold} />
+ )}
+ </div>
+ <div className={classes.ratting}>
+ <Rating value={detailContent.getIn([productIndex, 'ratting'])} max={5} readOnly />
+ </div>
+ <Typography component="p" className={classes.desc}>
+ {detailContent.getIn([productIndex, 'desc'])}
+ </Typography>
+ {!detailContent.getIn([productIndex, 'soldout']) && (
+ <div className={classes.btnArea}>
+ <Typography variant="subtitle1">
+ Quantity :
+ </Typography>
+ <TextField
+ type="number"
+ InputLabelProps={{
+ shrink: true,
+ }}
+ margin="none"
+ value={qty}
+ className={classes.quantity}
+ onChange={this.handleQtyChange}
+ />
+ <Button variant="contained" onClick={() => this.submitToCart(itemAttr(detailContent))} color="secondary">
+ <AddShoppingCart />
+ {' '}
+Add to cart
+ </Button>
+ </div>
+ )}
+ </section>
+ </Grid>
+ </Grid>
+ </div>
+ </Dialog>
+ );
+ }
+}
+
+ProductDetail.propTypes = {
+ classes: PropTypes.object.isRequired,
+ open: PropTypes.bool.isRequired,
+ close: PropTypes.func.isRequired,
+ handleAddToCart: PropTypes.func.isRequired,
+ detailContent: PropTypes.object.isRequired,
+ productIndex: PropTypes.number,
+};
+
+ProductDetail.defaultProps = {
+ productIndex: undefined
+};
+
+export default withStyles(styles)(ProductDetail);
diff --git a/front/odiparpack/app/components/Gallery/ProductGallery.js b/front/odiparpack/app/components/Gallery/ProductGallery.js
new file mode 100644
index 0000000..94f6c1e
--- /dev/null
+++ b/front/odiparpack/app/components/Gallery/ProductGallery.js
@@ -0,0 +1,152 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import ViewList from '@material-ui/icons/ViewList';
+import GridOn from '@material-ui/icons/GridOn';
+import { Grid, Typography, Button } from '@material-ui/core';
+import ProductCard from '../CardPaper/ProductCard';
+import ProductDetail from './ProductDetail';
+
+
+const styles = theme => ({
+ result: {
+ margin: theme.spacing(1)
+ },
+ option: {
+ display: 'flex',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ marginBottom: 10
+ },
+ button: {
+ fontSize: 12,
+ '& svg': {
+ marginRight: 10
+ }
+ },
+ appBar: {
+ position: 'relative',
+ },
+ flex: {
+ flex: 1,
+ },
+});
+
+class ProductGallery extends React.Component {
+ state = {
+ listView: false,
+ open: false,
+ }
+
+ handleDetailOpen = (product) => {
+ this.setState({ open: true });
+ this.props.showDetail(product);
+ };
+
+ handleClose = () => {
+ this.setState({ open: false });
+ };
+
+ handleSwitchView = () => {
+ this.setState({
+ listView: !this.state.listView
+ });
+ }
+
+ render() {
+ const { classes } = this.props;
+ const { listView, open } = this.state;
+ const {
+ dataProduct,
+ handleAddToCart,
+ productIndex,
+ keyword,
+ } = this.props;
+
+ const getTotalResult = dataArray => {
+ let totalResult = 0;
+ for (let i = 0; i < dataArray.size; i += 1) {
+ if (dataArray.getIn([i, 'name']) === undefined) {
+ return false;
+ }
+ if (dataArray.getIn([i, 'name']).toLowerCase().indexOf(keyword) !== -1) {
+ totalResult += 1;
+ }
+ }
+ return totalResult;
+ };
+
+ return (
+ <div>
+ <ProductDetail
+ open={open}
+ close={this.handleClose}
+ detailContent={dataProduct}
+ productIndex={productIndex}
+ handleAddToCart={handleAddToCart}
+ />
+ <section className={classes.option}>
+ <Typography variant="caption" className={classes.result}>
+ {getTotalResult(dataProduct)}
+ {' '}
+Results
+ </Typography>
+ <Button onClick={this.handleSwitchView} className={classes.button} size="small">
+ {listView ? <GridOn /> : <ViewList />}
+ {listView ? 'Grid View' : 'List View'}
+ </Button>
+ </section>
+ <Grid
+ container
+ alignItems="flex-start"
+ justify="flex-start"
+ direction="row"
+ spacing={3}
+ >
+ {
+ dataProduct.map((product, index) => {
+ if (product.get('name').toLowerCase().indexOf(keyword) === -1) {
+ return false;
+ }
+ const itemAttr = {
+ id: product.get('id'),
+ name: product.get('name'),
+ thumbnail: product.get('thumbnail'),
+ price: product.get('price'),
+ quantity: 1
+ };
+ return (
+ <Grid item md={listView ? 12 : 4} sm={listView ? 12 : 6} xs={12} key={index.toString()}>
+ <ProductCard
+ list={listView}
+ name={product.get('name')}
+ thumbnail={product.get('thumbnail')}
+ desc={product.get('desc')}
+ ratting={product.get('ratting')}
+ price={product.get('price')}
+ prevPrice={product.get('prevPrice')}
+ discount={product.get('discount')}
+ soldout={product.get('soldout')}
+ detailOpen={() => this.handleDetailOpen(product)}
+ addToCart={() => handleAddToCart(itemAttr)}
+ />
+ </Grid>
+ );
+ })
+ }
+ </Grid>
+ </div>
+ );
+ }
+}
+
+ProductGallery.propTypes = {
+ classes: PropTypes.object.isRequired,
+ dataProduct: PropTypes.object.isRequired,
+ handleAddToCart: PropTypes.func.isRequired,
+ showDetail: PropTypes.func.isRequired,
+ productIndex: PropTypes.number.isRequired,
+ keyword: PropTypes.string.isRequired,
+};
+
+export default withStyles(styles)(ProductGallery);
diff --git a/front/odiparpack/app/components/Gallery/photo-jss.js b/front/odiparpack/app/components/Gallery/photo-jss.js
new file mode 100644
index 0000000..61a6961
--- /dev/null
+++ b/front/odiparpack/app/components/Gallery/photo-jss.js
@@ -0,0 +1,79 @@
+const styles = theme => ({
+ masonry: { /* Masonry container */
+ [theme.breakpoints.up('sm')]: {
+ columnCount: 2,
+ },
+ [theme.breakpoints.up('md')]: {
+ columnCount: 3,
+ },
+ columnGap: '1em',
+ columnFill: 'initial',
+ marginTop: 20
+ },
+ item: {
+ display: 'inline-table',
+ margin: `0 0 ${theme.spacing(2)}px`,
+ width: '100%',
+ boxShadow: theme.shadows[4],
+ overflow: 'hidden',
+ borderRadius: 2,
+ transition: 'box-shadow .3s',
+ '&:hover': {
+ cursor: 'pointer',
+ boxShadow: theme.shadows[7],
+ },
+ '& img': {
+ marginBottom: -7
+ }
+ },
+ image: {
+ position: 'relative',
+ [theme.breakpoints.down('xs')]: {
+ width: '100% !important', // Overrides inline-style
+ },
+ '&:hover, &$focusVisible': {
+ zIndex: 1,
+ '& $imageBackdrop': {
+ opacity: 0.15,
+ },
+ },
+ },
+ focusVisible: {},
+ imageButton: {
+ position: 'absolute',
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0,
+ display: 'flex',
+ alignItems: 'flex-end',
+ justifyContent: 'center',
+ color: theme.palette.common.white,
+ paddingBottom: 10
+ },
+ imageBackdrop: {
+ position: 'absolute',
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0,
+ backgroundColor: theme.palette.common.black,
+ opacity: 0,
+ transition: theme.transitions.create('opacity'),
+ },
+ imageTitle: {
+ position: 'relative',
+ padding: `${theme.spacing(2)}px ${theme.spacing(4)}px ${theme.spacing(1) + 6}px`,
+ },
+ imageMarked: {
+ height: 3,
+ width: 18,
+ backgroundColor: theme.palette.common.white,
+ position: 'absolute',
+ bottom: -2,
+ left: 'calc(50% - 9px)',
+ transition: theme.transitions.create('opacity'),
+ },
+});
+
+export default styles;
diff --git a/front/odiparpack/app/components/Gallery/product-jss.js b/front/odiparpack/app/components/Gallery/product-jss.js
new file mode 100644
index 0000000..230ebf0
--- /dev/null
+++ b/front/odiparpack/app/components/Gallery/product-jss.js
@@ -0,0 +1,87 @@
+import { blueGrey as dark } from '@material-ui/core/colors';
+const styles = theme => ({
+ root: {
+ flexGrow: 1,
+ },
+ rootSlider: {
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'center'
+ },
+ item: {
+ textAlign: 'center',
+ '& img': {
+ margin: '10px auto'
+ }
+ },
+ appBar: {
+ position: 'relative',
+ },
+ flex: {
+ flex: 1,
+ },
+ detailContainer: {
+ margin: '-16px auto 0',
+ maxWidth: '100%',
+ [theme.breakpoints.up('lg')]: {
+ maxWidth: 1080,
+ },
+ [theme.breakpoints.up('md')]: {
+ maxWidth: 960,
+ paddingTop: 40,
+ marginTop: 0
+ },
+ [theme.breakpoints.down('sm')]: {
+ overflowX: 'hidden',
+ }
+ },
+ chipDiscount: {
+ background: theme.palette.primary.light,
+ color: theme.palette.primary.dark,
+ marginBottom: 10,
+ },
+ chipSold: {
+ background: dark[500],
+ color: theme.palette.getContrastText(dark[500]),
+ marginBottom: 10,
+ },
+ detailWrap: {
+ padding: 30
+ },
+ title: {
+ marginBottom: 30
+ },
+ price: {
+ display: 'flex',
+ alignItems: 'center',
+ marginTop: 30,
+ padding: '8px 12px',
+ '& > *': {
+ marginRight: 10
+ }
+ },
+ ratting: {
+ borderBottom: `1px solid ${theme.palette.grey[400]}`,
+ marginBottom: 20,
+ },
+ btnArea: {
+ display: 'flex',
+ alignItems: 'center',
+ marginTop: 20,
+ background: theme.palette.grey[100],
+ padding: '10px 20px'
+ },
+ quantity: {
+ width: 40,
+ marginRight: 40,
+ marginLeft: 10,
+ '& input': {
+ textAlign: 'right'
+ }
+ },
+ desc: {
+ padding: '10px 0'
+ }
+});
+
+export default styles;