Created
May 2, 2023 13:33
-
-
Save kali-physi-hacker/237161680b756d5a7adb7b58e9c7c19e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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