Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save kali-physi-hacker/237161680b756d5a7adb7b58e9c7c19e to your computer and use it in GitHub Desktop.
Save kali-physi-hacker/237161680b756d5a7adb7b58e9c7c19e to your computer and use it in GitHub Desktop.
// react
import React, {useEffect, useState} from "react";
// mui
import Page from "src/components/Page";
import {
Accordion,
AccordionDetails,
AccordionSummary,
Box,
Button,
Grid,
IconButton,
Stack,
Tooltip,
Typography,
useMediaQuery,
Tabs,
Tab,
TextField,
InputAdornment,
Slide
} from "@mui/material";
import {useTheme, styled} from "@mui/material/styles";
import RemoveIcon from "@mui/icons-material/Remove";
import AddIcon from "@mui/icons-material/Add";
import InfoIcon from "@mui/icons-material/Info";
// custom components
import Logo from "src/components/Logo";
// icons
import {SortIcon, SearchIcon, FilterIcon, BackIcon, CloseIcon} from "src/icons";
import {useDispatch, useSelector} from "src/redux/store";
import {getProducts} from "src/redux/slices/product";
import {HEADER} from "../../config";
import {makeStyles} from "@mui/styles";
const OptionButton = styled(Button)(({}) => ({
padding: "8px 24px",
minWidth: "160px",
fontFamily: "Minion Pro",
fontSize: "12px",
fontWeight: 700,
backgroundColor: "#262626",
color: "white",
}))
const TabPanel = (props) => {
const {merchantCode, children, value, ...other} = props;
return <div role="tabpanel"
hidden={value !== merchantCode}
id={`wine-listing-table-tabpanel-${merchantCode}`}
aria-labelledby={`wine-listing-table-tab-${merchantCode}`}
{...other}>
{value === merchantCode && children}
</div>
}
export default function WineListing() {
const theme = useTheme();
const dispatch = useDispatch();
useEffect(() => {
dispatch(getProducts());
}, [dispatch]);
const isDesktop = useMediaQuery(theme.breakpoints.up("md"));
const {
products: {data, metadata}, isLoading
} = useSelector((state) => state.product);
const ListingTableRow = ({property, value, xs = 3, tooltip}) => {
return (
<Grid xs={xs} sx={{minWidth: "83px"}} item>
<Typography sx={{color: "#9F9F9F"}} fontSize={10}>
{property}
</Typography>
<Typography
sx={{display: "inline-flex", alignItems: "center"}}
fontSize={10}
>
{value}{" "}
{tooltip && (
<Tooltip title={tooltip}>
<InfoIcon
sx={{ml: "4.5px", width: "11px", height: "11px"}}
fontSize={"small"}
/>
</Tooltip>
)}
</Typography>
</Grid>
);
};
const ListingTableHeadRow = ({
name,
isFirst = false,
isActive = false,
sub,
}) => {
let size = isDesktop ? 1 : 2;
if (isFirst) size = isDesktop ? 8 : 4;
return (
<Grid
sx={
isFirst
? {backgroundColor: theme.palette.background.main}
: {pl: "0 !important"}
}
xs={size}
item
>
<Typography
sx={{color: "rgba(255, 255, 255, 0.6)"}}
alignItems={"center"}
flexDirection={"row"}
component={Stack}
py={1}
fontSize={10}
>
<span style={{fontWeight: "bold"}}>{name}</span>
{sub && <>({sub})</>}
<SortIcon isActive={isActive} size={"small"}/>
</Typography>
</Grid>
);
};
const ListingBodyRowSummaryItem = ({
value,
value2,
color,
isFirst = false,
}) => {
let size = isDesktop ? 1 : 2;
if (isFirst) size = isDesktop ? 8 : 4;
const contSx = isFirst ? {pl: "0 !important", width: "100%"} : {};
return (
<Grid
sx={{alignItems: "center", display: "flex", ...contSx}}
xs={size}
item
>
<Typography
sx={isFirst ? {pl: 1.2, position: "relative"} : {}}
fontSize={10}
>
{isFirst && (
<span
style={{
position: "absolute",
top: 0,
left: 0,
backgroundColor: `#${color}`,
display: "inline-block",
width: "3px",
height: "100%",
}}
></span>
)}
{value}{" "}
{value2 && (
<>
<br/>
{value2}
</>
)}
</Typography>
</Grid>
);
};
const [showSearchInput, setShowSearchInput] = useState(false);
const [searchParam, setSearchParam] = useState("");
const clearSearch = () => {
setSearchParam("");
}
const searchProducts = () => {
dispatch(getProducts({q: searchParam}))
}
const SearchFilterComp = () => {
console.log("rendered")
const useStyles = makeStyles({
root: {
borderRadius: 4,
backgroundColor: "rgba(255, 255, 255, 0.1)",
paddingLeft: "8px 16px",
minWidth: "237px",
height: "35px"
},
input: {
padding: "8px 16px",
borderRadius: "4px"
},
underline: {
"&&&:before": {
borderBottom: "none"
},
"&&:after": {
borderBottom: "none"
}
}
});
const classes = useStyles();
const [searchParam2, setSearchParam2] = useState("");
return (
<Stack spacing={0} sx={{width: "100%", p: 0}} my={2} alignItems={"center"}
justifyContent={"space-evenly"} direction={"row"}>
{showSearchInput ?
<Slide in={showSearchInput} direction={"left"}>
<Stack spacing={0} sx={{width: "100%", p: 0}} alignItems={"center"}
justifyContent={"space-evenly"} direction={"row"}>
<BackIcon onClick={e => setShowSearchInput(false)}
sx={{color: "rgba(255, 255, 255, 0.6)"}}/>
<TextField value={searchParam} onChange={e => setSearchParam(e.target.value)} size={"small"}
sx={{alignSelf: "center", height: "35px"}} variant={"filled"}
InputProps={{
classes,
endAdornment: searchParam ?
<InputAdornment position={"end"}>
<CloseIcon
onClick={clearSearch}
sx={{width: "16px", height: "16px"}}/>
</InputAdornment> : null
}} name={"search-wine"}/>
<Button onClick={searchProducts} sx={{padding: "8px 16px"}} size={"small"}
variant={"contained"}>Search</Button>
</Stack>
</Slide> :
<Slide in={!showSearchInput} direction={"right"}>
<Stack spacing={0} sx={{width: "100%", p: 0}} direction={"row"} alignItems={"center"}
justifyContent={"space-evenly"} direction={"row"}>
<OptionButton sx={{minWidth: isDesktop ? "415px" : "160px"}}><FilterIcon
sx={{mr: 1, width: "12px", height: "12px"}}/> Filter</OptionButton>
<OptionButton onClick={e => setShowSearchInput(true)}
sx={{minWidth: isDesktop ? "415px" : "160px"}}><SearchIcon
sx={{mr: 1, width: "12px", height: "12px"}}/> Search</OptionButton>
</Stack>
</Slide>
}
</Stack>
)
}
// const searchFilter = <SearchFilterComp/>
const WineListingTableTabContent = ({filteredData, index}) => {
return (
<Grid id={index} sx={{
borderTopLeftRadius: "20px",
borderTopRightRadius: "20px",
contain: "paint",
backgroundColor: "#1C1C1C",
width: "calc(100% + 8px)"
}} container spacing={1}>
{/* {searchFilter} */}
{/* Table Head */}
<Stack
direction={"row"}
sx={{
mt: 2,
ml: 1.2,
backgroundColor: "#1C1C1C",
position: "sticky",
top: HEADER.DASHBOARD_DESKTOP_OFFSET_HEIGHT,
zIndex: 1000,
width: "100%",
}}
>
<ListingTableHeadRow name={"Wine"} isFirst/>
<ListingTableHeadRow isActive={true} name={"Vintage"}/>
<ListingTableHeadRow name={"Source"}/>
<ListingTableHeadRow name={"Lot"} sub={"SKU"}/>
<ListingTableHeadRow name={"Price"} sub={"750mL"}/>
</Stack>
{/* Table Body */}
{filteredData.map((row, index) => (
<React.Fragment key={index}>
<Accordion
disableGutters={true}
elevation={0}
sx={{
boxShadow: "none !important",
p: "0 !important",
width: "100%",
}}
>
<AccordionSummary sx={{backgroundColor: "#1C1C1C", width: "100%", p: "0 !important"}}>
<ListingBodyRowSummaryItem
color={row.type.color_code}
value={row.name}
isFirst
/>
<ListingBodyRowSummaryItem value={row.vintage}/>
<ListingBodyRowSummaryItem value={row.source}/>
<ListingBodyRowSummaryItem value={row.packing}/>
<ListingBodyRowSummaryItem
value={`${row.cash_price}`}
value2={`${row.coin_price}`}
/>
</AccordionSummary>
<AccordionDetails sx={{px: 1.2, pb: 3}}>
<Grid columnSpacing={2} rowSpacing={1} container>
{isDesktop ? (
<Grid
sx={{maxWidth: "700px", pl: 2}}
columnSpacing={2}
rowSpacing={1}
container
>
<ListingTableRow
xs={4}
property={"Producer"}
value={row.producer.full_name}
/>
<ListingTableRow
xs={4}
property={"Region"}
value={row.region}
/>
<ListingTableRow
xs={4}
property={"Notes"}
value={row.notes}
title={row.long_notes}
/>
<ListingTableRow
xs={2}
property={"Color/Type"}
value={row.type.code}
/>
<ListingTableRow
xs={2}
property={"Source"}
value={row.source}
tooltip={row.source_full_name}
/>
<ListingTableRow
xs={2}
property={"Bottle Volume"}
value={`${row.bottle_volume}mL`}
/>
<ListingTableRow
xs={2}
property={"LOT(SKU)"}
value={row.packing}
tooltip={"something"}
/>
<ListingTableRow
xs={2}
property={"Ex Domaine"}
value={"NE"}
/>
<ListingTableRow
xs={2}
property={"Merchant"}
value={row.merchant.code}
title={row.merchant.full_name}
/>
<ListingTableRow
xs={1}
property={"Price Per SKU"}
value={row.cash_price}
/>
<ListingTableRow
xs={2}
property={"Price Per 750mL"}
value={row.cash_price_per_750ml}
/>
<ListingTableRow
xs={2}
property={"Coin Per SKU"}
value={row.coin_price}
/>
<ListingTableRow
xs={2}
property={"Coin Per 750mL"}
value={row.coin_price_per_750ml}
/>
</Grid>
) : (
<>
<ListingTableRow
xs={6}
property={"Producer"}
value={row.producer.full_name}
/>
<ListingTableRow
xs={6}
property={"Region"}
value={row.region}
/>
<ListingTableRow
property={"Color/Type"}
value={row.type.code}
/>
<ListingTableRow
property={"Source"}
value={row.source}
tooltip={row.source_full_name}
/>
<ListingTableRow
property={"Bottle Volume"}
value={`${row.bottle_volume}mL`}
/>
<ListingTableRow
property={"LOT(SKU)"}
value={row.packing}
tooltip={"something"}
/>
<ListingTableRow
property={"Price Per SKU"}
value={row.cash_price}
/>
<ListingTableRow
property={"Price Per 750mL"}
value={row.cash_price_per_750ml}
/>
<ListingTableRow
property={"Coin Per SKU"}
value={row.coin_price}
/>
<ListingTableRow
property={"Coin Per 750mL"}
value={row.coin_price_per_750ml}
/>
<ListingTableRow property={"Ex Domaine"} value={"NE"}/>
<ListingTableRow
property={"Merchant"}
value={row.merchant.code}
title={row.merchant.full_name}
/>
<ListingTableRow
xs={6}
property={"Notes"}
value={row.notes}
title={row.long_notes}
/>
</>
)}
<Grid
sx={{
display: "inline-flex",
flexDirection: "row",
}}
xs={6}
item
>
<Box
sx={{
display: "flex",
alignItems: "center",
alignSelf: "end",
}}
>
<Logo iconWidth={11} iconHeight={11} isText={false}/>
<span
style={{
marginLeft: "4px",
fontWeight: "bold",
fontSize: 12,
color: "#FFFFFFCC",
}}
>
Recommended ∙ New Arrival
</span>
</Box>
</Grid>
<Box sx={{flexGrow: 1}}/>
<Grid sx={{pl: "0 !important"}} item>
<Stack pb={1} alignItems={"center"} direction={"row"}>
<IconButton>
<RemoveIcon/>
</IconButton>
<Typography
fontWeight={"bold"}
lineHeight={"12px"}
fontSize={10}
>
1 SKU
</Typography>
<IconButton>
<AddIcon/>
</IconButton>
</Stack>
<Button
sx={{width: "100%"}}
size={"small"}
py={"8px"}
px={"16px"}
variant={"contained"}
>
Add to Buy
</Button>
</Grid>
</Grid>
</AccordionDetails>
</Accordion>
</React.Fragment>
))}
</Grid>
)
}
const [merchantCode, setMerchantCode] = useState("full-list");
function a11yProps(merchantCode) {
return {
id: `wine-listing-table-tab-${merchantCode}`,
'aria-controls': `wine-listing-table-tabpanel-${merchantCode}`,
};
}
const changeTab = (_, merchantCode) => {
setShowSearchInput(false);
setMerchantCode(merchantCode);
if (merchantCode === "full-list") {
dispatch(getProducts());
return
}
dispatch(getProducts({merchant__code: merchantCode})); // merchantCode}));
}
const WineListingTabs = styled((props) => (
<Tabs
{...props}
TabIndicatorProps={{children: <span className="MuiTabs-indicatorSpan"/>}}
/>
))({
'& .MuiTabs-indicator': {
display: 'flex',
justifyContent: 'center',
backgroundColor: 'transparent',
height: 4,
},
'& .MuiTabs-indicatorSpan': {
maxWidth: 40,
width: '100%',
backgroundColor: "#877564"
},
});
const featuredMerchants = metadata?.featured_merchants || [];
return (
<Page sx={{pl: "8px"}} title={"Wine Listing"}>
<Box sx={{mb: 1}}>
<WineListingTabs variant={"scrollable"} value={merchantCode} onChange={changeTab}>
<Tab sx={{color: "#FFFFFF66", fontFamily: "Minion Pro", fontWeight: 700}} label={"Full List"}
value={"full-list"}/>
{featuredMerchants.map((merchant, index) => (
<Tab sx={{color: "#FFFFFF66", fontFamily: "Minion Pro", fontWeight: 700}} key={index}
label={merchant.full_name}
icon={<InfoIcon sx={{width: 12, height: 12, ml: 0.5}}/>} iconPosition={"end"}
value={merchant.code}/>
))}
</WineListingTabs>
</Box>
<SearchFilterComp />
<TabPanel value={"full-list"} merchantCode={merchantCode}>
<WineListingTableTabContent filteredData={data}/>
</TabPanel>
{featuredMerchants.map((merchant, index) => (
<TabPanel key={index} value={merchant.code} merchantCode={merchantCode}>
<WineListingTableTabContent index={index} filteredData={data}/>
</TabPanel>
))}
</Page>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment