| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588 |
- // styled components
- import {
- Link,
- SingleLink,
- StyledAccordion,
- StyledAccordionDetails,
- StyledAccordionSummary,
- StyledBonus,
- StyledButton,
- StyledThemeTabs,
- StyledThemeTab,
- StyledAct,
- StyledRefer,
- StyledBlock,
- StyledIconLink
- }
- from './styles';
- // components
- import Logo from '@components/Logo';
- import {NavLink, useLocation,useNavigate} from 'react-router-dom';
- // hooks
- import {useSidebar} from '@contexts/sidebarContext';
- import {useWindowSize} from 'react-use';
- import {Fragment, useEffect, useState} from 'react';
- // constants
- import LINKS from '@constants/links';
- import MuiDrawer from '@mui/material/Drawer';
- // import styled from 'styled-components/macro';
- import { styled, useTheme } from '@mui/material/styles';
- import SidebarTrigger from "@ui/SidebarTrigger";
- import {ReactComponent as CheckInIcon} from "@assets/singlesvg/chekin.svg";
- // import {useThemeProvider} from '@contexts/themeContext';
- import symbol from '@assets/symbol-defs.svg';
- import MTooltip from "@components/MTooltip";
- import Tabs from "@mui/material/Tabs";
- import Tab from "@mui/material/Tab";
- import Button from "@mui/material/Button";
- import TabScrollButton from "@mui/material/TabScrollButton";
- import ToggleButtonGroup from "@mui/material/ToggleButtonGroup";
- import {useThemeProvider} from "@contexts/themeContext";
- import questsimg from "@assets/activity/quests.png";
- import spin_1 from "@assets/activity/spin_1.png";
- import spin_2 from "@assets/activity/spin_2.png";
- import spin_3 from "@assets/activity/spin_3.png";
- import imgrefer from "@assets/activity/rio_refer.png";
- import imgrefer_f from "@assets/activity/rio_refer_f.png";
- import {useDispatch, useSelector} from "react-redux";
- import {
- allNavs,
- getBlockColumn,
- getRoute,
- getRouteStyles,
- isFullRoute,
- isLogined,
- logout,
- nBlocks
- } from "@features/mainSlice";
- import {
- ROUTE_PATH,
- ROUTE_TYPE_OUTLINK,
- ROUTE_TYPE_POP,
- ROUTE_TYPE_POP_OR_FULL,
- SIDE_TYPE_GRID,
- SIDE_TYPE_NOMAL,
- SIDE_TYPE_SPECIAL
- } from "@constants/routes";
- import SvgIcon from "@components/SvgIcon";
- import {reqChangeInfo, reqLogout} from "@features/api";
- import {APP_THEME} from "@constants/app";
- const drawWidth = 250;
- const drawMobieWidth=250;
- const i18n=global.i18n;
- const openedMixin = (theme,width) => ({
- width: width,
- transition: theme.transitions.create('width', {
- easing: theme.transitions.easing.sharp,
- duration: theme.transitions.duration.enteringScreen,
- }),
- // overflowX: 'hidden',
- overflow:'visible !important',
- backgroundColor:'var(--standard);',
- boxShadow:'var(--widget-shadow);',
- // position:'relative',
- });
- const closedMixin = (theme) => ({
- transition: theme.transitions.create('width', {
- easing: theme.transitions.easing.sharp,
- duration: theme.transitions.duration.leavingScreen,
- }),
- // overflowX: 'hidden',
- //spin显示
- overflow:'visible !important',
- width: `calc(${theme.spacing(7)} + 1px)`,
- [theme.breakpoints.up('sm')]: {
- width: `calc(${theme.spacing(8)} + 1px)`,
- },
- backgroundColor:'var(--standard);',
- boxShadow:'var(--widget-shadow);',
- // position:'absolute',
- });
- const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== 'open' })(
- ({ theme, open}) => ({
- width: drawWidth,
- flexShrink: 0,
- whiteSpace: 'nowrap',
- boxSizing: 'border-box',
- pointerEvents: 'auto',
- // overflowX:'hidden',
- ...(open && {
- ...openedMixin(theme),
- '& .MuiDrawer-paper': openedMixin(theme,drawWidth),
- }),
- ...(!open && {
- ...closedMixin(theme),
- '& .MuiDrawer-paper': closedMixin(theme),
- }),
- }),
- );
- const DrawerHeader = styled('div')(({ theme }) => ({
- display: 'flex',
- alignItems: 'center',
- padding: '0 10px',
- gap:'12px',
- // backgroundColor:'#000',
- boxShadow:'var(--widget-shadow)',
- position:'relative',
- '& .logo_con':{
- width:'80%'
- },
- '& .logo_con_m':{
- width:'80%'
- },
- // necessary for content to be below app bar
- ...theme.mixins.toolbar,
- }));
- const Sidebar = () => {
- // const theme = useTheme();
- const {open, setOpen} = useSidebar();
- const [expanded, setExpanded] = useState("");
- const {pathname,hash} = useLocation();
- const navigate=useNavigate();
- const {width} = useWindowSize();
- const {theme, toggleTheme, setIsShowLang, isMobile} = useThemeProvider();
- const [isActHovered, setIsActHovered] = useState(false);
- const visiblecls=isActHovered?"overflow-visible":"";
- const navBlocks=useSelector(nBlocks);
- const currRoute = useSelector(getRoute(pathname));
- const blocksColumn=useSelector(getBlockColumn);
- const routeStyles=useSelector(getRouteStyles);
- const isLogin=useSelector(isLogined);
- const dispatch = useDispatch();
- const handleActEnter = () => {
- if (open)return;
- setIsActHovered(true);
- };
- const handleActLeave = () => {
- if (open)return;
- setIsActHovered(false);
- };
- // manually handle accordion expansion
- const handleChange = (panel,path) => (event, isExpanded) => {
- if (isExpanded)navigate(path);
- // setExpanded(isExpanded ? panel : false);
- if (!isExpanded){
- let arr=panel.split("_");
- let s=arr.length-2;
- if (s<0)panel="";
- else
- {
- arr.splice(s,1);
- panel=arr.join("_");
- }
- }
- setExpanded(panel);
- }
- const checkNavOpen=()=>{
- if (currRoute==null)return;
- let lv=currRoute.lv;
- setExpanded(lv);
- }
- const getolstyles=(styleID)=>{
- let styles=routeStyles[styleID];
- if (styles==null){
- styles=routeStyles[1];
- }
- let style={};
- if (styles!=null){
- style=styles.style;
- }
- let thstyles=style[theme];
- if (thstyles==null)thstyles={};
- return thstyles;
- }
- // collapse opened accordion on route change when the drawer is temporary
- useEffect(() => {
- checkNavOpen();
- }, [pathname]);
- const checkCkey=(lv)=>{
- if (expanded==null)return false;
- else return expanded.startsWith(lv);
- }
- const checkPath=(link)=>{
- let lv=currRoute.lv;
- return lv===link.lv;
- }
- const renderIconLink=(link,olstyle,lIcon=null)=>{
- let ispop=link.type===ROUTE_TYPE_POP||link.type===ROUTE_TYPE_POP_OR_FULL||link.type===ROUTE_TYPE_OUTLINK;
- let linkIcon=(<SvgIcon className={"icon"} herf={link.icon}/>);
- if (lIcon!=null)linkIcon=lIcon;
- let target=link.type===ROUTE_TYPE_OUTLINK?"_blank":"";
- let linkA=ispop?(
- <a href={link.path} target={target}>
- {linkIcon}
- </a>
- ):(
- <NavLink to={link.path}>
- {linkIcon}
- </NavLink>
- );
- return (
- <MTooltip disableHoverListener={open} title={i18n.t(link.title)} arrow placement="right">
- <StyledIconLink olstyle={olstyle}>
- {linkA}
- </StyledIconLink>
- </MTooltip>
- );
- }
- const renderLink=(link)=>{
- let pages=link.subs||link.pages;
- let styles=getolstyles(link.style);
- let linkItem=open?(
- <StyledAccordion olstyle={styles} defaultExpanded={true} square={true} key={link.lv} expanded={checkCkey(link.lv)} onChange={handleChange(`${link.lv}`,link.path)}>
- <StyledAccordionSummary olstyle={styles}>
- <Link olstyle={styles} className={`${checkPath(link) ? 'active' : ''} h4`}>
- <SvgIcon className={"icon"} herf={link.icon}/>
- {i18n.t(link.title)}
- </Link>
- <SvgIcon className={"icon-chevron-down"} herf={'icon_Arrow'}/>
- </StyledAccordionSummary>
- <StyledAccordionDetails olstyle={styles}>
- {
- pages.map((page,pindex)=>{
- let subs=page.subs;
- if (subs==null||subs.length==0)return renderRLink(page);
- else
- {
- return renderLink(page);
- }
- })
- }
- </StyledAccordionDetails>
- </StyledAccordion>
- ):renderIconLink(link,styles);
- return linkItem
- }
- const renderRLink=(link)=>{
- let isActive=checkPath(link);
- let ispop=link.type===ROUTE_TYPE_POP||link.type===ROUTE_TYPE_POP_OR_FULL||link.type===ROUTE_TYPE_OUTLINK;
- let clname=`${isActive?'active':''} h4`;
- let linktxt=(
- <>
- <SvgIcon className={"icon"} herf={link.icon}/>
- <span>{i18n.t(`${link.title}`)}</span>
- </>
- )
- let target=link.type===ROUTE_TYPE_OUTLINK?"_blank":"";
- return ispop?(<a className={clname} target={target} href={link.path}>{linktxt}</a>):(<NavLink className={clname} to={link.path}>{linktxt}</NavLink>)
- }
- const renderSingleLink=(link)=>{
- let styles=getolstyles(link.style);
- return open?(
- <SingleLink olstyle={styles}>
- {
- renderRLink(link)
- }
- </SingleLink>
- ):renderIconLink(link,styles)
- }
- const renderLinkNav=(link)=>{
- let linkItem=(<></>);
- let subs=link.subs;
- let len=subs.length;
- if (len===0&&link.plv===""){
- linkItem=renderSingleLink(link);
- }
- else
- {
- linkItem=renderLink(link);
- }
- return linkItem;
- }
- const renderBlock=(block,bkey)=>{
- if (block==null)return (<Fragment key={`b_empty_${bkey}`}/>);
- let first=block[0];
- if (first==null)return (<Fragment key={`b_first_${bkey}`}/>);
- let blockID=first.block;
- let column=1;
- if (blocksColumn!=null){
- let blockC=blocksColumn[blockID];
- if (blockC!=null)column=blockC.column;
- }
- return (
- <Fragment key={`b_${blockID||bkey}`}>
- <StyledBlock open={open} column={column}>
- {
- block.map((link, index) => {
- return (<Fragment key={link.id||link.path||index}>{renderLinkNav(link)}</Fragment>)
- })
- }
- </StyledBlock>
- {renderLine()}
- </Fragment>
- )
- }
- const renderLinkBlocks=()=>{
- return (
- <>
- {
- navBlocks.map((block,index)=>{
- return renderBlock(block,index);
- })
- }
- </>
- )
- }
- const renderBonus=()=>{
- let styles=getolstyles(0);
- const ICON_SIZE={width:'1.5rem',height:'1.5rem',flex:'none'};
- // 桌面端用 hash 路由(#/promotion / #/bonus),由 RouteContainer 渲染成
- // popup-big 弹窗,当前页面 URL/内容不变;移动端继续走 /promotion / /bonus 全屏页。
- const desktop = !isMobile();
- const promotionPath = desktop ? "#/promotion" : ROUTE_PATH.PROMOTION;
- const bonusPath = desktop ? "#/bonus" : ROUTE_PATH.BONUS;
- const items=[
- {title:'links.promotion', icon:'icon_Giftbox', path:promotionPath, color:'#3bc117'},
- {title:'links.bonus', icon:'icon_Gift', path:bonusPath, color:'#b891ff'},
- {title:'links.share_rewards', icon:null, path:ROUTE_PATH.CASH_WHEEL, spin:true},
- ];
- const isActive=(p)=>pathname===p||(p && pathname.startsWith(p) && p!=='/');
- const spinIcon=(
- <span className="icon" style={{position:'relative',width:'1.7rem',height:'1.7rem',display:'inline-flex',alignItems:'center',justifyContent:'center',flex:'none',overflow:'visible',maxHeight:'none',maxWidth:'none'}}>
- <img src={spin_1} alt="" style={{position:'absolute',width:'1.55rem',height:'1.55rem',zIndex:1}}/>
- <img src={spin_2} alt="" style={{position:'absolute',width:'1.6rem',height:'1.6rem',zIndex:2,animation:'rotate 2s infinite linear'}}/>
- <img src={spin_3} alt="" style={{position:'absolute',width:'0.9rem',height:'auto',zIndex:3,marginTop:'-0.75em'}}/>
- </span>
- );
- const renderRow=(it)=>{
- const iconNode=it.spin?spinIcon:(
- <SvgIcon className={"icon"} herf={it.icon} style={{...ICON_SIZE, fill: it.color}}/>
- );
- const link={type:0,title:it.title,icon:it.icon||'icon_Share',path:it.path};
- if (!open){
- return (<span key={it.title}>{renderIconLink(link,styles,iconNode)}</span>);
- }
- return (
- <SingleLink key={it.title} olstyle={styles}>
- <NavLink className={`${isActive(it.path)?'active':''} h4`} to={it.path} style={{padding:'0.7rem 0.825rem',gap:'0.75rem'}}>
- {iconNode}
- <span style={{fontSize:'0.95rem',fontWeight:600,lineHeight:'1.2rem',whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}}>
- {i18n.t(it.title)}
- </span>
- </NavLink>
- </SingleLink>
- );
- };
- return (
- <StyledBlock open={open}>
- <StyledBonus className="d-flex flex-column g-6" open={open}>
- {items.map(renderRow)}
- </StyledBonus>
- </StyledBlock>
- );
- }
- const renderLogout=()=>{
- return (
- <>
- {
- isLogin?(
- <StyledButton open={open} className="h4" onClick={()=>{
- dispatch(reqLogout());
- setOpen(false);
- }}>
- <SvgIcon className={"icon"} herf={"icon_Logout"}/>
- {open?i18n.t("links.log_out"):""}
- </StyledButton>
- ):(<></>)
- }
- </>
- )
- }
- const renderLanguage=()=>{
- return (
- <StyledBlock open={open}>
- <MTooltip disableHoverListener={open} title={i18n.t("quickbar.language")} arrow placement="right">
- <StyledButton open={open} className="h4" onClick={()=>{
- if (typeof setIsShowLang === "function") setIsShowLang(true);
- setOpen(false);
- }}>
- <SvgIcon className={"icon"} herf={"icon_Language"}/>
- {open?i18n.t("quickbar.language"):""}
- </StyledButton>
- </MTooltip>
- </StyledBlock>
- )
- }
- const renderSuport=()=>{
- return (
- <StyledBlock open={open}>
- {/*{renderLogout()}*/}
- <MTooltip disableHoverListener={open} title={i18n.t("links.live_support")} arrow placement="right">
- <StyledButton open={open} className="h4" fill={"#3bc117"} onClick={()=>{
- if (global.showCustomerService) global.showCustomerService();
- }}>
- <SvgIcon className={"icon"} herf={"icon_Support"}/>
- {open?i18n.t("links.live_support"):""}
- </StyledButton>
- </MTooltip>
- </StyledBlock>
- )
- }
- const handleTheme = (event, value) => {
- if (value){
- toggleTheme();
- }
- if (!isLogin)return;
- dispatch(reqChangeInfo({
- ThemeColor:value
- }));
- // console.log(value)
- }
- const renderThemeTabs=()=>{
- if (open){
- return (
- <StyledBlock open={open} >
- <StyledThemeTabs sx={{
- marginTop:'16px',
- }} className={theme} exclusive value={theme} onChange={handleTheme}>
- <div className="theme-bg"/>
- <StyledThemeTab value={APP_THEME.DARK}>
- <SvgIcon className={"icon"} herf={"icon_Dark"}/>
- {i18n.t("theme.dark")}
- </StyledThemeTab>
- <StyledThemeTab value={APP_THEME.LIGHT}>
- <SvgIcon className={"icon"} herf={"icon_Light"}/>
- {i18n.t("theme.light")}
- </StyledThemeTab>
- </StyledThemeTabs>
- </StyledBlock>
- )
- }
- else return(<></>);
- }
- const renderLine=(key="1")=>{
- // if (open)return(<></>);
- // else
- // {
- // return (
- // <div className="fold-line"></div>
- // )
- // }
- return (
- <div className="fold-line"></div>
- )
- }
- const renderBanner=()=>{
- let refimg=open?imgrefer:imgrefer_f;
- return (
- <StyledBlock open={open}>
- <MTooltip disableHoverListener={open} title={i18n.t("refer.title")} arrow placement="right">
- <StyledRefer open={open}>
- <img alt={"refer"} src={refimg}/>
- {
- open?(
- <div className={"ref-right"}>
- <div className={"t"}>{i18n.t("refer.title")}</div>
- <div className={"s"}>{i18n.t("refer.des")}</div>
- </div>
- ):(<></>)
- }
- </StyledRefer>
- </MTooltip>
- </StyledBlock>
- )
- }
- const renderContent=(showLanguage=false)=>{
- return (
- <>
- {renderBonus()}
- {/*{renderBanner()}*/}
- {renderLine()}
- {renderLinkBlocks()}
- {renderSuport()}
- {showLanguage?renderLanguage():null}
- {renderThemeTabs()}
- </>
- )
- }
- const renderDesktop=()=>{
- return (
- <Drawer variant="permanent" open={open} sx={{
- }}>
- <DrawerHeader>
- <SidebarTrigger/>
- {
- open?(
- <div className={'logo_con'}>
- <Logo/>
- </div>
- ):<></>
- }
- </DrawerHeader>
- <div className={`d-flex flex-column sidebar-nav ${visiblecls}`}>
- <div className={`d-flex flex-column g-4 ${visiblecls}`}>
- {
- renderContent()
- }
- </div>
- </div>
- </Drawer>
- )
- }
- const renderMobile=()=>{
- return (
- <MuiDrawer open={open} sx={{
- pointerEvents: 'auto',
- "& .MuiDrawer-paper": {
- width: drawMobieWidth,
- boxSizing: "border-box",
- overflow:'visible !important',
- backgroundColor:'var(--standard);',
- boxShadow:'var(--widget-shadow);',
- },
- "& .MuiModal-backdrop":{
- backgroundColor:'rgba(0,0,0,0)',
- }
- }} variant="temporary" onClose={()=>{
- setOpen(false);
- }}>
- <DrawerHeader>
- <SidebarTrigger/>
- {
- open?(
- <div className={'logo_con_m'}>
- <Logo/>
- </div>
- ):<></>
- }
- </DrawerHeader>
- <div className={`d-flex flex-column sidebar-nav ${visiblecls}`}>
- <div className={`d-flex flex-column g-4 ${visiblecls}`}>
- {
- renderContent(true)
- }
- </div>
- </div>
- </MuiDrawer>
- )
- }
- return (
- <>
- {
- isMobile()?(renderMobile()):renderDesktop()
- }
- </>
- )
- }
- export default Sidebar
|