diff --git a/components/AppAppBar.tsx b/components/AppAppBar.tsx index 8c5ad96..a0ebf47 100644 --- a/components/AppAppBar.tsx +++ b/components/AppAppBar.tsx @@ -146,7 +146,7 @@ function AppAppBar({ user }: AppAppBarProps) { variant="contained" size="small" component="a" - href="/api/auth/login" + href="/dashboard" startIcon={} > Dashboard diff --git a/components/artist.tsx b/components/Old/artist.tsx similarity index 100% rename from components/artist.tsx rename to components/Old/artist.tsx diff --git a/components/Old/artistDashboardRequest.tsx b/components/Old/artistDashboardRequest.tsx new file mode 100644 index 0000000..532e80a --- /dev/null +++ b/components/Old/artistDashboardRequest.tsx @@ -0,0 +1,53 @@ +import * as React from 'react'; +import { useEffect, useState } from "react"; +import { Grid, Card, CardContent, Typography } from '@mui/material'; +import CircularProgress from '@mui/material/CircularProgress'; +import Box from '@mui/material/Box'; + + +const ArtistDashboardRequest = () => { + const [sellerRequestData, setSellerRequestData] = useState(null); + + const getData = async () => { + const response = await fetch('/api/artist/request'); + const sellerProfile = await response.json(); + setSellerRequestData(sellerProfile); + } + useEffect(() => { + getData(); + }, []); + + let formattedTime = "" + if (sellerRequestData) { + const date = new Date(sellerRequestData["requestDate"]); + formattedTime = date.toLocaleTimeString('en-US', { month: 'long', day: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }); // Example format + } + + return ( + (sellerRequestData ? ( + + + + + Request Status + + {(sellerRequestData["accepted"] ? ( + Accepted + ) : ( + Pending + ))} + Request submitted on {formattedTime ?? ''} + + ) : ( + + + + Loading + + + + + )) + ) + } +export default ArtistDashboardRequest \ No newline at end of file diff --git a/components/artistPortfolio.tsx b/components/Old/artistPortfolio.tsx similarity index 72% rename from components/artistPortfolio.tsx rename to components/Old/artistPortfolio.tsx index 3d5c47e..fc29e1b 100644 --- a/components/artistPortfolio.tsx +++ b/components/Old/artistPortfolio.tsx @@ -3,7 +3,7 @@ import {ImageList, Box, Typography, CircularProgress} from '@mui/material'; import { useEffect, useState } from "react"; import ArtistPortfolioImage from './artistPortfolioImage'; -const ArtistPortfolio = ({artistId}) => { +const ArtistPortfolio = ({masonry,columns,artistId}) => { const [portfolioData, setPortfolioData] = useState([]); const [loading, setLoading] = useState(true); // State for loading indicator useEffect(() => { @@ -26,11 +26,19 @@ const ArtistPortfolio = ({artistId}) => { ) : ( - + (masonry) ? ( + {portfolioData.map((item) => ( ))} + ):( + + {portfolioData.map((item) => ( + + ))} + + ) ) ) } diff --git a/components/artistPortfolioImage.tsx b/components/Old/artistPortfolioImage.tsx similarity index 96% rename from components/artistPortfolioImage.tsx rename to components/Old/artistPortfolioImage.tsx index 55e6900..b7004b7 100644 --- a/components/artistPortfolioImage.tsx +++ b/components/Old/artistPortfolioImage.tsx @@ -14,7 +14,7 @@ const ArtistPortfolioImage = ({artistId,itemId}) => { }; return ( - + { const [portfolioData, setPortfolioData] = useState([]); const [loading, setLoading] = useState(true); // State for loading indicator diff --git a/components/editableArtistPortfolioImage.tsx b/components/Old/editableArtistPortfolioImage.tsx similarity index 100% rename from components/editableArtistPortfolioImage.tsx rename to components/Old/editableArtistPortfolioImage.tsx diff --git a/components/header.tsx b/components/Old/header.tsx similarity index 100% rename from components/header.tsx rename to components/Old/header.tsx diff --git a/components/layout.tsx b/components/Old/layout.tsx similarity index 96% rename from components/layout.tsx rename to components/Old/layout.tsx index 0ddff72..ca925ae 100644 --- a/components/layout.tsx +++ b/components/Old/layout.tsx @@ -1,5 +1,5 @@ import Head from "next/head"; -import Header from "./header"; +import Header from "../header"; type LayoutProps = { user?: any; diff --git a/components/swipableView.tsx b/components/Old/swipableView.tsx similarity index 100% rename from components/swipableView.tsx rename to components/Old/swipableView.tsx diff --git a/components/Onboarding.tsx b/components/Onboarding.tsx new file mode 100644 index 0000000..543bfcd --- /dev/null +++ b/components/Onboarding.tsx @@ -0,0 +1,218 @@ +import * as React from 'react'; +import Box from '@mui/material/Box'; +import Stepper from '@mui/material/Stepper'; +import Step from '@mui/material/Step'; +import StepLabel from '@mui/material/StepLabel'; +import StepContent from '@mui/material/StepContent'; +import Button from '@mui/material/Button'; +import Paper from '@mui/material/Paper'; +import Typography from '@mui/material/Typography'; +import Grid from '@mui/material/Grid' +import TextField from '@mui/material/TextField'; +import ArtistDashboardRequest from '../components/Old/artistDashboardRequest'; +import ArtistPortfolio from '../components/Old/artistPortfolio'; +import EditableArtistPortfolio from '../components/Old/editableArtistPortfolio'; +import { useEffect, useState } from "react"; + +import CurrencyTextField from '@lupus-ai/mui-currency-textfield'; +import {Card, CardContent, CardHeader, Divider } from '@mui/material'; + + +const steps = [ + { + label: 'Request Access As Artist', + description: `In order to start selling your art on our platform, you need to request access. Please include links to your social media and tag or DM us on the platform (@RequestDotBox). We may reach out for further verification and examples of your work.`, + }, + { + label: 'Onboard On Stripe', + description: + 'Our platform uses Stripe as a payment processor. You will be required to onboard with them with all of your payout information and business information.', + }, + { + label: 'Setup Your Portfolio', + description: `This is where you can setup your initial portfolio. You can upload any image format file to your portfolio. It will be automatically displayed on your artist page. You can add and remove from this later.`, + }, +]; + +export default function Onboarding() { + const [activeStep, setActiveStep] = React.useState(0); + const [sellerRequestData, setSellerRequestData] = React.useState(null); + const [profileData, setSellerProfileData] = React.useState(null); + const [isStripeOnboarded, setIsStripeOnboarded] = React.useState(false); + const [onBoardUrl, setOnBoardUrl] = React.useState(""); + + + + const handleNext = () => { + setActiveStep((prevActiveStep) => prevActiveStep + 1); + }; + + const handleBack = () => { + setActiveStep((prevActiveStep) => prevActiveStep - 1); + }; + + const handleReset = () => { + setActiveStep(0); + }; + + const getData = async () => { + const onboardCheckRequest = await fetch('/api/artist/onboarded', { method: "GET" }); + const onboardCheckResponse = await onboardCheckRequest.json(); + setIsStripeOnboarded(onboardCheckResponse["onboarded"]); + const onboardUrlRequest = await fetch('/api/artist/onboardurl', { method: "GET" }); + const onboardUrlResponse = await onboardUrlRequest.json(); + setOnBoardUrl(onboardUrlResponse["onboardUrl"]); + const response = await fetch('/api/artist/request'); + const sellerRequest = await response.json(); + setSellerRequestData(sellerRequest); + const profileResponse = await fetch('/api/artist/profile'); + const sellerProfile = await profileResponse.json(); + setSellerProfileData(sellerProfile); + + setTimeout(getData, 5000); // Poll every 5 seconds (adjust as needed) + } + React.useEffect(() => { + getData(); + }, []); + + const requestButton = () => { + fetch('/api/artist/newRequest').then((response) => { + if (response.ok) { + fetch('/api/artist/request').then((requestResponse) => { + requestResponse.json().then((sellerRequest) => { + setSellerRequestData(sellerRequest); + }); + }); + } + }); + } + + let formattedTime = "" + if (sellerRequestData) { + const date = new Date(sellerRequestData["requestDate"]); + formattedTime = date.toLocaleTimeString('en-US', { month: 'long', day: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }); // Example format + } + + return ( + + + {steps.map((step, index) => ( + + Last step + ) : null + } + > + {step.label} + + {(index==0) ? ( + + + + {step.description} + + {(sellerRequestData && Object.keys(sellerRequestData).length>0) ? ( + + + + ):( + + + + )} + + + + {(sellerRequestData && Object.keys(sellerRequestData).length>0) ? ( + (sellerRequestData["accepted"]) ? ( + + Continue + + ) : ( + + + Request Pending + ) + ): + ( + + + Request Access + + )} + + + + ): null} + {(index==1) ? ( + + + + {step.description} + + + + + {isStripeOnboarded==true ? ( + + Continue + + ):( + + + ONBOARD WITH STRIPE + + )} + + + + ): null} + {(index==2) ? ( + + + + {step.description} + + + + + + + + + {index === steps.length - 1 ? 'Finish' : 'Continue'} + + + + + ): null} + + ))} + + {activeStep === steps.length && ( + + We are setting up your account please wait. + + )} + + ); +} \ No newline at end of file diff --git a/components/Orders.tsx b/components/Orders.tsx new file mode 100644 index 0000000..8f173c7 --- /dev/null +++ b/components/Orders.tsx @@ -0,0 +1,33 @@ +import * as React from 'react'; +import { DataGrid, GridColDef, GridValueGetterParams } from '@mui/x-data-grid'; +import { Button } from '@mui/material'; + +const columns: GridColDef[] = [ + { field: 'id', headerName: 'ID', width: 70 }, + { field: 'artist', headerName: 'Artist', width: 130 }, + { field: 'status', headerName: 'Status', width: 130 }, + { field: 'action', headerName: 'Action', width: 180, renderCell: (params) => { + return (View More); + }}, +]; + +const rows = [ + { id: 1, artist:'Neroshi', status: 'Pending'}, +]; + +export default function Orders() { + return ( + + + + ); +} diff --git a/components/artistDashboardRequest.tsx b/components/artistDashboardRequest.tsx deleted file mode 100644 index a8182ac..0000000 --- a/components/artistDashboardRequest.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import * as React from 'react'; -import { useEffect, useState } from "react"; -import { Grid, Card, CardContent, Typography } from '@mui/material'; -import CircularProgress from '@mui/material/CircularProgress'; -import Box from '@mui/material/Box'; - - -const ArtistDashboardRequest = () => { - const [sellerRequestData, setSellerRequestData] = useState(null); - - const getData = async () => { - const response = await fetch('/api/artist/profile'); - const sellerProfile = await response.json(); - setSellerRequestData(sellerProfile); - } - useEffect(() => { - getData(); - }, []); - - let formattedTime = "" - if (sellerRequestData) { - const date = new Date(sellerRequestData["requestDate"]); - formattedTime = date.toLocaleTimeString('en-US', { month: 'long', day: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }); // Example format - } - - const requestButton = () => { - fetch('/api/artist/newRequest').then((response) => { - if (response.ok) { - fetch('/api/artist/request').then((requestResponse) => { - requestResponse.json().then((sellerRequest) => { - setSellerRequestData(sellerRequest); - getData(); - }); - }); - } - }); - } - - return ( - (sellerRequestData ? ( - - - - - Request Status - - {(sellerRequestData["accepted"] ? ( - Accepted - ) : ( - Pending - ))} - Request submitted on {formattedTime ?? ''} - - - ) : ( - - - - Loading - - - - - )) - ) - } -export default ArtistDashboardRequest \ No newline at end of file diff --git a/pages/dashboard.tsx b/components/withOnboardingRequired.tsx similarity index 100% rename from pages/dashboard.tsx rename to components/withOnboardingRequired.tsx diff --git a/configs/themeConfig.tsx b/configs/themeConfig.tsx new file mode 100644 index 0000000..1d02c6b --- /dev/null +++ b/configs/themeConfig.tsx @@ -0,0 +1,36 @@ +// ** MUI Imports +import { PaletteMode } from '@mui/material' + +// ** Types +import { ContentWidth } from '../core/layouts/types' + +type ThemeConfig = { + mode: PaletteMode + templateName: string + routingLoader: boolean + disableRipple: boolean + navigationSize: number + menuTextTruncate: boolean + contentWidth: ContentWidth + responsiveFontSizes: boolean +} + +const themeConfig: ThemeConfig = { + // ** Layout Configs + templateName: 'Request.Box' /* App Name */, + mode: 'light' /* light | dark */, + contentWidth: 'boxed' /* full | boxed */, + + // ** Routing Configs + routingLoader: true /* true | false */, + + // ** Navigation (Menu) Configs + menuTextTruncate: true /* true | false */, + navigationSize: 260 /* Number in PX(Pixels) /*! Note: This is for Vertical navigation menu only */, + + // ** Other Configs + responsiveFontSizes: true /* true | false */, + disableRipple: false /* true | false */ +} + +export default themeConfig diff --git a/core/components/card-statistics/card-stats-vertical/index.tsx b/core/components/card-statistics/card-stats-vertical/index.tsx new file mode 100644 index 0000000..04efd09 --- /dev/null +++ b/core/components/card-statistics/card-stats-vertical/index.tsx @@ -0,0 +1,54 @@ +// ** MUI Imports +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import Avatar from '@mui/material/Avatar' +import IconButton from '@mui/material/IconButton' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' + +// ** Icons Imports +import DotsVertical from 'mdi-material-ui/DotsVertical' + +// ** Types Imports +import { CardStatsVerticalProps } from '../core/components/card-statistics/types' + +const CardStatsVertical = (props: CardStatsVerticalProps) => { + // ** Props + const { title, subtitle, color, icon, stats, trend, trendNumber } = props + + return ( + + + + + {icon} + + + + + + {title} + + + {stats} + + + {trendNumber} + + + {subtitle} + + + ) +} + +export default CardStatsVertical + +CardStatsVertical.defaultProps = { + color: 'primary', + trend: 'positive' +} diff --git a/core/components/card-statistics/types.ts b/core/components/card-statistics/types.ts new file mode 100644 index 0000000..0d5371b --- /dev/null +++ b/core/components/card-statistics/types.ts @@ -0,0 +1,15 @@ +// ** React Imports +import { ReactNode } from 'react' + +// ** Types +import { ThemeColor } from '../core/layouts/types' + +export type CardStatsVerticalProps = { + title: string + stats: string + icon: ReactNode + subtitle: string + color?: ThemeColor + trendNumber: string + trend?: 'positive' | 'negative' +} diff --git a/core/components/react-apexcharts/index.tsx b/core/components/react-apexcharts/index.tsx new file mode 100644 index 0000000..e8d2b2d --- /dev/null +++ b/core/components/react-apexcharts/index.tsx @@ -0,0 +1,7 @@ +// ** Next Import +import dynamic from 'next/dynamic' + +// ! To avoid 'Window is not defined' error +const ReactApexcharts = dynamic(() => import('react-apexcharts'), { ssr: false }) + +export default ReactApexcharts diff --git a/core/components/scroll-to-top/index.tsx b/core/components/scroll-to-top/index.tsx new file mode 100644 index 0000000..30bed5d --- /dev/null +++ b/core/components/scroll-to-top/index.tsx @@ -0,0 +1,47 @@ +// ** React Imports +import { ReactNode } from 'react' + +// ** MUI Imports +import Zoom from '@mui/material/Zoom' +import { styled } from '@mui/material/styles' +import useScrollTrigger from '@mui/material/useScrollTrigger' + +interface ScrollToTopProps { + className?: string + children: ReactNode +} + +const ScrollToTopStyled = styled('div')(({ theme }) => ({ + zIndex: 11, + position: 'fixed', + right: theme.spacing(6), + bottom: theme.spacing(10) +})) + +const ScrollToTop = (props: ScrollToTopProps) => { + // ** Props + const { children, className } = props + + // ** init trigger + const trigger = useScrollTrigger({ + threshold: 400, + disableHysteresis: true + }) + + const handleClick = () => { + const anchor = document.querySelector('body') + if (anchor) { + anchor.scrollIntoView({ behavior: 'smooth' }) + } + } + + return ( + + + {children} + + + ) +} + +export default ScrollToTop diff --git a/core/context/settingsContext.tsx b/core/context/settingsContext.tsx new file mode 100644 index 0000000..adf2df5 --- /dev/null +++ b/core/context/settingsContext.tsx @@ -0,0 +1,47 @@ +// ** React Imports +import { createContext, useState, ReactNode } from 'react' + +// ** MUI Imports +import { PaletteMode } from '@mui/material' + +// ** ThemeConfig Import +import themeConfig from '../../configs/themeConfig' + +// ** Types Import +import { ThemeColor, ContentWidth } from '../../core/layouts/types' + +export type Settings = { + mode: PaletteMode + themeColor: ThemeColor + contentWidth: ContentWidth +} + +export type SettingsContextValue = { + settings: Settings + saveSettings: (updatedSettings: Settings) => void +} + +const initialSettings: Settings = { + themeColor: 'primary', + mode: themeConfig.mode, + contentWidth: themeConfig.contentWidth +} + +// ** Create Context +export const SettingsContext = createContext({ + saveSettings: () => null, + settings: initialSettings +}) + +export const SettingsProvider = ({ children }: { children: ReactNode }) => { + // ** State + const [settings, setSettings] = useState({ ...initialSettings }) + + const saveSettings = (updatedSettings: Settings) => { + setSettings(updatedSettings) + } + + return {children} +} + +export const SettingsConsumer = SettingsContext.Consumer diff --git a/core/hooks/useSettings.ts b/core/hooks/useSettings.ts new file mode 100644 index 0000000..bdf3047 --- /dev/null +++ b/core/hooks/useSettings.ts @@ -0,0 +1,4 @@ +import { useContext } from 'react' +import { SettingsContext, SettingsContextValue } from '../../core/context/settingsContext' + +export const useSettings = (): SettingsContextValue => useContext(SettingsContext) diff --git a/core/layouts/BlankLayout.tsx b/core/layouts/BlankLayout.tsx new file mode 100644 index 0000000..7c86693 --- /dev/null +++ b/core/layouts/BlankLayout.tsx @@ -0,0 +1,40 @@ +// ** MUI Imports +import { styled } from '@mui/material/styles' +import Box, { BoxProps } from '@mui/material/Box' + +// ** Types +import { BlankLayoutProps } from './types' + +// Styled component for Blank Layout component +const BlankLayoutWrapper = styled(Box)(({ theme }) => ({ + height: '100vh', + + // For V1 Blank layout pages + '& .content-center': { + display: 'flex', + minHeight: '100vh', + alignItems: 'center', + justifyContent: 'center', + padding: theme.spacing(5) + }, + + // For V2 Blank layout pages + '& .content-right': { + display: 'flex', + minHeight: '100vh', + overflowX: 'hidden', + position: 'relative' + } +})) + +const BlankLayout = ({ children }: BlankLayoutProps) => { + return ( + + + {children} + + + ) +} + +export default BlankLayout diff --git a/core/layouts/VerticalLayout.tsx b/core/layouts/VerticalLayout.tsx new file mode 100644 index 0000000..5e50e70 --- /dev/null +++ b/core/layouts/VerticalLayout.tsx @@ -0,0 +1,118 @@ +// ** React Imports +import { useState } from 'react' + +// ** MUI Imports +import Fab from '@mui/material/Fab' +import { styled } from '@mui/material/styles' +import Box, { BoxProps } from '@mui/material/Box' + +// ** Icons Imports +import ArrowUp from 'mdi-material-ui/ArrowUp' + +// ** Theme Config Import +import themeConfig from '../../configs/themeConfig' + +// ** Type Import +import { LayoutProps } from '../../core/layouts/types' + +// ** Components +import AppBar from './components/vertical/appBar' +import Navigation from './components/vertical/navigation' +import Footer from './components/shared-components/footer' +import ScrollToTop from '../../core/components/scroll-to-top' + +// ** Styled Component +import DatePickerWrapper from '../../core/styles/libs/react-datepicker' + +const VerticalLayoutWrapper = styled('div')({ + height: '100%', + display: 'flex' +}) + +const MainContentWrapper = styled(Box)({ + flexGrow: 1, + minWidth: 0, + display: 'flex', + minHeight: '100vh', + flexDirection: 'column' +}) + +const ContentWrapper = styled('main')(({ theme }) => ({ + flexGrow: 1, + width: '100%', + padding: theme.spacing(6), + transition: 'padding .25s ease-in-out', + [theme.breakpoints.down('sm')]: { + paddingLeft: theme.spacing(4), + paddingRight: theme.spacing(4) + } +})) + +const VerticalLayout = (props: LayoutProps) => { + // ** Props + const { settings, children, scrollToTop } = props + + // ** Vars + const { contentWidth } = settings + const navWidth = themeConfig.navigationSize + + // ** States + const [navVisible, setNavVisible] = useState(false) + + // ** Toggle Functions + const toggleNavVisibility = () => setNavVisible(!navVisible) + + return ( + <> + + {/* Navigation Menu */} + + + {/* AppBar Component */} + + + {/* Content */} + + {children} + + + {/* Footer Component */} + + + {/* Portal for React Datepicker */} + + + + + + + {/* Scroll to top button */} + {scrollToTop ? ( + scrollToTop(props) + ) : ( + + + + + + )} + > + ) +} + +export default VerticalLayout diff --git a/core/layouts/components/shared-components/ModeToggler.tsx b/core/layouts/components/shared-components/ModeToggler.tsx new file mode 100644 index 0000000..cf5f80f --- /dev/null +++ b/core/layouts/components/shared-components/ModeToggler.tsx @@ -0,0 +1,40 @@ +// ** MUI Imports +import { PaletteMode } from '@mui/material' +import IconButton from '@mui/material/IconButton' + +// ** Icons Imports +import WeatherNight from 'mdi-material-ui/WeatherNight' +import WeatherSunny from 'mdi-material-ui/WeatherSunny' + +// ** Type Import +import { Settings } from '../core/context/settingsContext' + +interface Props { + settings: Settings + saveSettings: (values: Settings) => void +} + +const ModeToggler = (props: Props) => { + // ** Props + const { settings, saveSettings } = props + + const handleModeChange = (mode: PaletteMode) => { + saveSettings({ ...settings, mode }) + } + + const handleModeToggle = () => { + if (settings.mode === 'light') { + handleModeChange('dark') + } else { + handleModeChange('light') + } + } + + return ( + + {settings.mode === 'dark' ? : } + + ) +} + +export default ModeToggler diff --git a/core/layouts/components/shared-components/NotificationDropdown.tsx b/core/layouts/components/shared-components/NotificationDropdown.tsx new file mode 100644 index 0000000..bebf219 --- /dev/null +++ b/core/layouts/components/shared-components/NotificationDropdown.tsx @@ -0,0 +1,217 @@ +// ** React Imports +import { useState, SyntheticEvent, Fragment, ReactNode } from 'react' + +// ** MUI Imports +import Box from '@mui/material/Box' +import Chip from '@mui/material/Chip' +import Button from '@mui/material/Button' +import IconButton from '@mui/material/IconButton' +import { styled, Theme } from '@mui/material/styles' +import useMediaQuery from '@mui/material/useMediaQuery' +import MuiMenu, { MenuProps } from '@mui/material/Menu' +import MuiAvatar, { AvatarProps } from '@mui/material/Avatar' +import MuiMenuItem, { MenuItemProps } from '@mui/material/MenuItem' +import Typography, { TypographyProps } from '@mui/material/Typography' + +// ** Icons Imports +import BellOutline from 'mdi-material-ui/BellOutline' + +// ** Third Party Components +import PerfectScrollbarComponent from 'react-perfect-scrollbar' + +// ** Styled Menu component +const Menu = styled(MuiMenu)(({ theme }) => ({ + '& .MuiMenu-paper': { + width: 380, + overflow: 'hidden', + marginTop: theme.spacing(4), + [theme.breakpoints.down('sm')]: { + width: '100%' + } + }, + '& .MuiMenu-list': { + padding: 0 + } +})) + +// ** Styled MenuItem component +const MenuItem = styled(MuiMenuItem)(({ theme }) => ({ + paddingTop: theme.spacing(3), + paddingBottom: theme.spacing(3), + borderBottom: `1px solid ${theme.palette.divider}` +})) + +const styles = { + maxHeight: 349, + '& .MuiMenuItem-root:last-of-type': { + border: 0 + } +} + +// ** Styled PerfectScrollbar component +const PerfectScrollbar = styled(PerfectScrollbarComponent)({ + ...styles +}) + +// ** Styled Avatar component +const Avatar = styled(MuiAvatar)({ + width: '2.375rem', + height: '2.375rem', + fontSize: '1.125rem' +}) + +// ** Styled component for the title in MenuItems +const MenuItemTitle = styled(Typography)(({ theme }) => ({ + fontWeight: 600, + flex: '1 1 100%', + overflow: 'hidden', + fontSize: '0.875rem', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + marginBottom: theme.spacing(0.75) +})) + +// ** Styled component for the subtitle in MenuItems +const MenuItemSubtitle = styled(Typography)({ + flex: '1 1 100%', + overflow: 'hidden', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis' +}) + +const NotificationDropdown = () => { + // ** States + const [anchorEl, setAnchorEl] = useState<(EventTarget & Element) | null>(null) + + // ** Hook + const hidden = useMediaQuery((theme: Theme) => theme.breakpoints.down('lg')) + + const handleDropdownOpen = (event: SyntheticEvent) => { + setAnchorEl(event.currentTarget) + } + + const handleDropdownClose = () => { + setAnchorEl(null) + } + + const ScrollWrapper = ({ children }: { children: ReactNode }) => { + if (hidden) { + return {children} + } else { + return ( + {children} + ) + } + } + + return ( + + + + + + + + Notifications + + + + + + + + + Congratulation Flora! 🎉 + Won the monthly best seller badge + + + Today + + + + + + VU + + New user registered. + 5 hours ago + + + Yesterday + + + + + + + + New message received 👋🏻 + You have 10 unread messages + + + 11 Aug + + + + + + + + Paypal + Received Payment + + + 25 May + + + + + + + + Revised Order 📦 + New order revised from john + + + 19 Mar + + + + + + + + Finance report has been generated + 25 hrs ago + + + 27 Dec + + + + + `1px solid ${theme.palette.divider}` }} + > + + Read All Notifications + + + + + ) +} + +export default NotificationDropdown diff --git a/core/layouts/components/shared-components/UserDropdown.tsx b/core/layouts/components/shared-components/UserDropdown.tsx new file mode 100644 index 0000000..d2e672d --- /dev/null +++ b/core/layouts/components/shared-components/UserDropdown.tsx @@ -0,0 +1,162 @@ +// ** React Imports +import { useState, SyntheticEvent, Fragment } from 'react' + +// ** Next Import +import { useRouter } from 'next/router' + +// ** MUI Imports +import Box from '@mui/material/Box' +import Menu from '@mui/material/Menu' +import Badge from '@mui/material/Badge' +import Avatar from '@mui/material/Avatar' +import Divider from '@mui/material/Divider' +import MenuItem from '@mui/material/MenuItem' +import { styled } from '@mui/material/styles' +import Typography from '@mui/material/Typography' + +// ** Icons Imports +import CogOutline from 'mdi-material-ui/CogOutline' +import CurrencyUsd from 'mdi-material-ui/CurrencyUsd' +import EmailOutline from 'mdi-material-ui/EmailOutline' +import LogoutVariant from 'mdi-material-ui/LogoutVariant' +import AccountOutline from 'mdi-material-ui/AccountOutline' +import MessageOutline from 'mdi-material-ui/MessageOutline' +import HelpCircleOutline from 'mdi-material-ui/HelpCircleOutline' + +import { useUser } from '@auth0/nextjs-auth0/client' + +// ** Styled Components +const BadgeContentSpan = styled('span')(({ theme }) => ({ + width: 8, + height: 8, + borderRadius: '50%', + backgroundColor: theme.palette.success.main, + boxShadow: `0 0 0 2px ${theme.palette.background.paper}` +})) + +const UserDropdown = () => { + const { user, isLoading } = useUser(); + + // ** States + const [anchorEl, setAnchorEl] = useState(null) + + // ** Hooks + const router = useRouter() + + const handleDropdownOpen = (event: SyntheticEvent) => { + setAnchorEl(event.currentTarget) + } + + const handleDropdownClose = (url?: string) => { + if (url) { + router.push(url) + } + setAnchorEl(null) + } + + const styles = { + py: 2, + px: 4, + width: '100%', + display: 'flex', + alignItems: 'center', + color: 'text.primary', + textDecoration: 'none', + '& svg': { + fontSize: '1.375rem', + color: 'text.secondary' + } + } + + return ( + (!isLoading && user) ? ( + + } + anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }} + > + + + handleDropdownClose()} + sx={{ '& .MuiMenu-paper': { width: 230, marginTop: 4 } }} + anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }} + transformOrigin={{ vertical: 'top', horizontal: 'right' }} + > + + + } + anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }} + > + + + + {user.nickname} + + Welcome back! + + + + + + handleDropdownClose()}> + + + Profile + + + handleDropdownClose()}> + + + Inbox + + + handleDropdownClose()}> + + + Chat + + + + handleDropdownClose()}> + + + Settings + + + handleDropdownClose()}> + + + Pricing + + + handleDropdownClose()}> + + + FAQ + + + + handleDropdownClose('/api/auth/logout')}> + + Logout + + + + ): null + ) +} + +export default UserDropdown diff --git a/core/layouts/components/shared-components/footer/FooterContent.tsx b/core/layouts/components/shared-components/footer/FooterContent.tsx new file mode 100644 index 0000000..25a1cc4 --- /dev/null +++ b/core/layouts/components/shared-components/footer/FooterContent.tsx @@ -0,0 +1,18 @@ +// ** MUI Imports +import Box from '@mui/material/Box' +import Link from '@mui/material/Link' +import { Theme } from '@mui/material/styles' +import Typography from '@mui/material/Typography' +import useMediaQuery from '@mui/material/useMediaQuery' + +const FooterContent = () => { + // ** Var + const hidden = useMediaQuery((theme: Theme) => theme.breakpoints.down('md')) + + return ( + + + ) +} + +export default FooterContent diff --git a/core/layouts/components/shared-components/footer/index.tsx b/core/layouts/components/shared-components/footer/index.tsx new file mode 100644 index 0000000..80abc2b --- /dev/null +++ b/core/layouts/components/shared-components/footer/index.tsx @@ -0,0 +1,57 @@ +// ** React Imports +import { ReactNode } from 'react' + +// ** MUI Imports +import Box from '@mui/material/Box' +import { useTheme } from '@mui/material/styles' + +// ** Type Import +import { Settings } from '../core/context/settingsContext' + +// ** Footer Content Component +import FooterContent from './FooterContent' + +interface Props { + settings: Settings + saveSettings: (values: Settings) => void + footerContent?: (props?: any) => ReactNode +} + +const Footer = (props: Props) => { + // ** Props + const { settings, footerContent: userFooterContent } = props + + // ** Hook + const theme = useTheme() + + // ** Vars + const { contentWidth } = settings + + return ( + + + {userFooterContent ? userFooterContent(props) : } + + + ) +} + +export default Footer diff --git a/core/layouts/components/vertical/appBar/index.tsx b/core/layouts/components/vertical/appBar/index.tsx new file mode 100644 index 0000000..5127b57 --- /dev/null +++ b/core/layouts/components/vertical/appBar/index.tsx @@ -0,0 +1,70 @@ +// ** React Imports +import { ReactNode } from 'react' + +// ** MUI Imports +import { styled, useTheme } from '@mui/material/styles' +import MuiAppBar, { AppBarProps } from '@mui/material/AppBar' +import MuiToolbar, { ToolbarProps } from '@mui/material/Toolbar' + +// ** Type Import +import { Settings } from '../core/context/settingsContext' + +interface Props { + hidden: boolean + settings: Settings + toggleNavVisibility: () => void + saveSettings: (values: Settings) => void + verticalAppBarContent?: (props?: any) => ReactNode +} + +const AppBar = styled(MuiAppBar)(({ theme }) => ({ + transition: 'none', + alignItems: 'center', + justifyContent: 'center', + padding: theme.spacing(0, 6), + backgroundColor: 'transparent', + color: theme.palette.text.primary, + minHeight: theme.mixins.toolbar.minHeight, + [theme.breakpoints.down('sm')]: { + paddingLeft: theme.spacing(4), + paddingRight: theme.spacing(4) + } +})) + +const Toolbar = styled(MuiToolbar)(({ theme }) => ({ + width: '100%', + borderBottomLeftRadius: 10, + borderBottomRightRadius: 10, + padding: `${theme.spacing(0)} !important`, + minHeight: `${theme.mixins.toolbar.minHeight}px !important`, + transition: + 'padding .25s ease-in-out, box-shadow .25s ease-in-out, backdrop-filter .25s ease-in-out, background-color .25s ease-in-out' +})) + +const LayoutAppBar = (props: Props) => { + // ** Props + const { settings, verticalAppBarContent: userVerticalAppBarContent } = props + + // ** Hooks + const theme = useTheme() + + // ** Vars + const { contentWidth } = settings + + return ( + + + {(userVerticalAppBarContent && userVerticalAppBarContent(props)) || null} + + + ) +} + +export default LayoutAppBar diff --git a/core/layouts/components/vertical/navigation/Drawer.tsx b/core/layouts/components/vertical/navigation/Drawer.tsx new file mode 100644 index 0000000..101c0b5 --- /dev/null +++ b/core/layouts/components/vertical/navigation/Drawer.tsx @@ -0,0 +1,82 @@ +// ** React Imports +import { ReactNode } from 'react' + +// ** MUI Imports +import { styled, useTheme } from '@mui/material/styles' +import MuiSwipeableDrawer, { SwipeableDrawerProps } from '@mui/material/SwipeableDrawer' + +// ** Type Import +import { Settings } from '../core/context/settingsContext' + +interface Props { + hidden: boolean + navWidth: number + settings: Settings + navVisible: boolean + children: ReactNode + setNavVisible: (value: boolean) => void + saveSettings: (values: Settings) => void +} + +const SwipeableDrawer = styled(MuiSwipeableDrawer)({ + overflowX: 'hidden', + transition: 'width .25s ease-in-out', + '& ul': { + listStyle: 'none' + }, + '& .MuiListItem-gutters': { + paddingLeft: 4, + paddingRight: 4 + }, + '& .MuiDrawer-paper': { + left: 'unset', + right: 'unset', + overflowX: 'hidden', + transition: 'width .25s ease-in-out, box-shadow .25s ease-in-out' + } +}) + +const Drawer = (props: Props) => { + // ** Props + const { hidden, children, navWidth, navVisible, setNavVisible } = props + + // ** Hook + const theme = useTheme() + + // Drawer Props for Mobile & Tablet screens + const MobileDrawerProps = { + open: navVisible, + onOpen: () => setNavVisible(true), + onClose: () => setNavVisible(false), + ModalProps: { + keepMounted: true // Better open performance on mobile. + } + } + + // Drawer Props for Desktop screens + const DesktopDrawerProps = { + open: true, + onOpen: () => null, + onClose: () => null + } + + return ( + + {children} + + ) +} + +export default Drawer diff --git a/core/layouts/components/vertical/navigation/VerticalNavHeader.tsx b/core/layouts/components/vertical/navigation/VerticalNavHeader.tsx new file mode 100644 index 0000000..228e507 --- /dev/null +++ b/core/layouts/components/vertical/navigation/VerticalNavHeader.tsx @@ -0,0 +1,75 @@ +// ** React Import +import { ReactNode } from 'react' + +// ** Next Import +import Link from 'next/link' + +// ** MUI Imports +import Box, { BoxProps } from '@mui/material/Box' +import { styled, useTheme } from '@mui/material/styles' +import Typography, { TypographyProps } from '@mui/material/Typography' + +// ** Type Import +import { Settings } from '../../../../../core/context/settingsContext' + +// ** Configs +import themeConfig from '../../../../../configs/themeConfig' + +interface Props { + hidden: boolean + settings: Settings + toggleNavVisibility: () => void + saveSettings: (values: Settings) => void + verticalNavMenuBranding?: (props?: any) => ReactNode +} + +// ** Styled Components +const MenuHeaderWrapper = styled(Box)(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + paddingRight: theme.spacing(4.5), + transition: 'padding .25s ease-in-out', + minHeight: theme.mixins.toolbar.minHeight +})) + +const HeaderTitle = styled(Typography)(({ theme }) => ({ + fontWeight: 600, + lineHeight: 'normal', + textTransform: 'uppercase', + color: theme.palette.text.primary, + transition: 'opacity .25s ease-in-out, margin .25s ease-in-out' +})) + +const StyledLink = styled('a')({ + display: 'flex', + alignItems: 'center', + textDecoration: 'none' +}) + +const VerticalNavHeader = (props: Props) => { + // ** Props + const { verticalNavMenuBranding: userVerticalNavMenuBranding } = props + + // ** Hooks + const theme = useTheme() + + return ( + + {userVerticalNavMenuBranding ? ( + userVerticalNavMenuBranding(props) + ) : ( + + + + + {themeConfig.templateName} + + + + )} + + ) +} + +export default VerticalNavHeader diff --git a/core/layouts/components/vertical/navigation/VerticalNavItems.tsx b/core/layouts/components/vertical/navigation/VerticalNavItems.tsx new file mode 100644 index 0000000..bdd1980 --- /dev/null +++ b/core/layouts/components/vertical/navigation/VerticalNavItems.tsx @@ -0,0 +1,39 @@ +// ** Types Import +import { Settings } from '../core/context/settingsContext' +import { NavLink, NavSectionTitle, VerticalNavItemsType } from '../core/layouts/types' + +// ** Custom Menu Components +import VerticalNavLink from './VerticalNavLink' +import VerticalNavSectionTitle from './VerticalNavSectionTitle' + +interface Props { + settings: Settings + navVisible?: boolean + groupActive: string[] + currentActiveGroup: string[] + verticalNavItems?: VerticalNavItemsType + saveSettings: (values: Settings) => void + setGroupActive: (value: string[]) => void + setCurrentActiveGroup: (item: string[]) => void +} + +const resolveNavItemComponent = (item: NavLink | NavSectionTitle) => { + if ((item as NavSectionTitle).sectionTitle) return VerticalNavSectionTitle + + return VerticalNavLink +} + +const VerticalNavItems = (props: Props) => { + // ** Props + const { verticalNavItems } = props + + const RenderMenuItems = verticalNavItems?.map((item: NavLink | NavSectionTitle, index: number) => { + const TagName: any = resolveNavItemComponent(item) + + return + }) + + return <>{RenderMenuItems}> +} + +export default VerticalNavItems diff --git a/core/layouts/components/vertical/navigation/VerticalNavLink.tsx b/core/layouts/components/vertical/navigation/VerticalNavLink.tsx new file mode 100644 index 0000000..85fc735 --- /dev/null +++ b/core/layouts/components/vertical/navigation/VerticalNavLink.tsx @@ -0,0 +1,136 @@ +// ** React Imports +import { ElementType, ReactNode } from 'react' + +// ** Next Imports +import Link from 'next/link' +import { useRouter } from 'next/router' + +// ** MUI Imports +import Chip from '@mui/material/Chip' +import ListItem from '@mui/material/ListItem' +import { styled } from '@mui/material/styles' +import Typography from '@mui/material/Typography' +import Box, { BoxProps } from '@mui/material/Box' +import ListItemIcon from '@mui/material/ListItemIcon' +import ListItemButton, { ListItemButtonProps } from '@mui/material/ListItemButton' + +// ** Configs Import +import themeConfig from '../../../../../configs/themeConfig' + +// ** Types +import { NavLink } from '../../../../../core/layouts/types' +import { Settings } from '../../../../../core/context/settingsContext' + +// ** Custom Components Imports +import UserIcon from '../../../../../layouts/components/UserIcon' + +// ** Utils +import { handleURLQueries } from '../../../../../core/layouts/utils' + +interface Props { + item: NavLink + settings: Settings + navVisible?: boolean + toggleNavVisibility: () => void +} + +// ** Styled Components +const MenuNavLink = styled(ListItemButton)< + ListItemButtonProps & { component?: ElementType; target?: '_blank' | undefined } +>(({ theme }) => ({ + width: '100%', + borderTopRightRadius: 100, + borderBottomRightRadius: 100, + color: theme.palette.text.primary, + padding: theme.spacing(2.25, 3.5), + transition: 'opacity .25s ease-in-out', + '&.active, &.active:hover': { + boxShadow: theme.shadows[3], + backgroundImage: `linear-gradient(98deg, ${theme.palette.customColors.primaryGradient}, ${theme.palette.primary.main} 94%)` + }, + '&.active .MuiTypography-root, &.active .MuiSvgIcon-root': { + color: `${theme.palette.common.white} !important` + } +})) + +const MenuItemTextMetaWrapper = styled(Box)({ + width: '100%', + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + transition: 'opacity .25s ease-in-out', + ...(themeConfig.menuTextTruncate && { overflow: 'hidden' }) +}) + +const VerticalNavLink = ({ item, navVisible, toggleNavVisibility }: Props) => { + // ** Hooks + const router = useRouter() + + const IconTag: ReactNode = item.icon + + const isNavLinkActive = () => { + if (router.pathname === item.path || handleURLQueries(router, item.path)) { + return true + } else { + return false + } + } + + return ( + + + { + if (item.path === undefined) { + e.preventDefault() + e.stopPropagation() + } + if (navVisible) { + toggleNavVisibility() + } + }} + sx={{ + pl: 5.5, + ...(item.disabled ? { pointerEvents: 'none' } : { cursor: 'pointer' }) + }} + > + + + + + + {item.title} + {item.badgeContent ? ( + + ) : null} + + + + + ) +} + +export default VerticalNavLink diff --git a/core/layouts/components/vertical/navigation/VerticalNavSectionTitle.tsx b/core/layouts/components/vertical/navigation/VerticalNavSectionTitle.tsx new file mode 100644 index 0000000..1135d1b --- /dev/null +++ b/core/layouts/components/vertical/navigation/VerticalNavSectionTitle.tsx @@ -0,0 +1,72 @@ +// ** MUI Imports +import Divider from '@mui/material/Divider' +import { styled, useTheme } from '@mui/material/styles' +import Typography, { TypographyProps } from '@mui/material/Typography' +import MuiListSubheader, { ListSubheaderProps } from '@mui/material/ListSubheader' + +// ** Types +import { NavSectionTitle } from '../core/layouts/types' + +interface Props { + item: NavSectionTitle +} + +// ** Styled Components +const ListSubheader = styled((props: ListSubheaderProps) => )( + ({ theme }) => ({ + lineHeight: 1, + display: 'flex', + position: 'relative', + marginTop: theme.spacing(7), + marginBottom: theme.spacing(2), + backgroundColor: 'transparent', + transition: 'padding-left .25s ease-in-out' + }) +) + +const TypographyHeaderText = styled(Typography)(({ theme }) => ({ + fontSize: '0.75rem', + lineHeight: 'normal', + letterSpacing: '0.21px', + textTransform: 'uppercase', + color: theme.palette.text.disabled, + fontWeight: theme.typography.fontWeightMedium +})) + +const VerticalNavSectionTitle = (props: Props) => { + // ** Props + const { item } = props + + // ** Hook + const theme = useTheme() + + return ( + + + {item.sectionTitle} + + + ) +} + +export default VerticalNavSectionTitle diff --git a/core/layouts/components/vertical/navigation/index.tsx b/core/layouts/components/vertical/navigation/index.tsx new file mode 100644 index 0000000..6915313 --- /dev/null +++ b/core/layouts/components/vertical/navigation/index.tsx @@ -0,0 +1,153 @@ +// ** React Import +import { ReactNode, useRef, useState } from 'react' + +// ** MUI Import +import List from '@mui/material/List' +import Box, { BoxProps } from '@mui/material/Box' +import { styled, useTheme } from '@mui/material/styles' + +// ** Third Party Components +import PerfectScrollbar from 'react-perfect-scrollbar' + +// ** Type Import +import { Settings } from '../../../../../core/context/settingsContext' +import { VerticalNavItemsType } from '../../../../../core/layouts/types' + +// ** Component Imports +import Drawer from './Drawer' +import VerticalNavItems from './VerticalNavItems' +import VerticalNavHeader from './VerticalNavHeader' + +// ** Util Import +import { hexToRGBA } from '../../../../../core/utils/hex-to-rgba' + +interface Props { + hidden: boolean + navWidth: number + settings: Settings + children: ReactNode + navVisible: boolean + toggleNavVisibility: () => void + setNavVisible: (value: boolean) => void + verticalNavItems?: VerticalNavItemsType + saveSettings: (values: Settings) => void + verticalNavMenuContent?: (props?: any) => ReactNode + afterVerticalNavMenuContent?: (props?: any) => ReactNode + beforeVerticalNavMenuContent?: (props?: any) => ReactNode +} + +const StyledBoxForShadow = styled(Box)({ + top: 50, + left: -8, + zIndex: 2, + height: 75, + display: 'none', + position: 'absolute', + pointerEvents: 'none', + width: 'calc(100% + 15px)', + '&.d-block': { + display: 'block' + } +}) + +const Navigation = (props: Props) => { + // ** Props + const { + hidden, + afterVerticalNavMenuContent, + beforeVerticalNavMenuContent, + verticalNavMenuContent: userVerticalNavMenuContent + } = props + + // ** States + const [groupActive, setGroupActive] = useState([]) + const [currentActiveGroup, setCurrentActiveGroup] = useState([]) + + // ** Ref + const shadowRef = useRef(null) + + // ** Hooks + const theme = useTheme() + + // ** Fixes Navigation InfiniteScroll + const handleInfiniteScroll = (ref: HTMLElement) => { + if (ref) { + // @ts-ignore + ref._getBoundingClientRect = ref.getBoundingClientRect + + ref.getBoundingClientRect = () => { + // @ts-ignore + const original = ref._getBoundingClientRect() + + return { ...original, height: Math.floor(original.height) } + } + } + } + + // ** Scroll Menu + const scrollMenu = (container: any) => { + container = hidden ? container.target : container + if (shadowRef && container.scrollTop > 0) { + // @ts-ignore + if (!shadowRef.current.classList.contains('d-block')) { + // @ts-ignore + shadowRef.current.classList.add('d-block') + } + } else { + // @ts-ignore + shadowRef.current.classList.remove('d-block') + } + } + + const ScrollWrapper = hidden ? Box : PerfectScrollbar + + return ( + + + + + {/* @ts-ignore */} + scrollMenu(container), + sx: { height: '100%', overflowY: 'auto', overflowX: 'hidden' } + } + : { + options: { wheelPropagation: false }, + onScrollY: (container: any) => scrollMenu(container), + containerRef: (ref: any) => handleInfiniteScroll(ref) + })} + > + {beforeVerticalNavMenuContent ? beforeVerticalNavMenuContent(props) : null} + + {userVerticalNavMenuContent ? ( + userVerticalNavMenuContent(props) + ) : ( + + + + )} + + + + {afterVerticalNavMenuContent ? afterVerticalNavMenuContent(props) : null} + + ) +} + +export default Navigation diff --git a/core/layouts/types.ts b/core/layouts/types.ts new file mode 100644 index 0000000..b890144 --- /dev/null +++ b/core/layouts/types.ts @@ -0,0 +1,46 @@ +import { ReactNode } from 'react' +import { Settings } from '../core/context/settingsContext' + +export type ContentWidth = 'full' | 'boxed' + +export type ThemeColor = 'primary' | 'secondary' | 'error' | 'warning' | 'info' | 'success' + +export type NavLink = { + path?: string + title: string + action?: string + subject?: string + disabled?: boolean + badgeContent?: string + externalLink?: boolean + openInNewTab?: boolean + icon?: string | string[] | ReactNode + badgeColor?: 'default' | 'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info' +} + +export type NavSectionTitle = { + sectionTitle: string + action?: string + subject?: string +} + +export type VerticalNavItemsType = (NavLink | NavSectionTitle)[] + +export type LayoutProps = { + hidden: boolean + settings: Settings + children: ReactNode + verticalNavItems?: VerticalNavItemsType + scrollToTop?: (props?: any) => ReactNode + saveSettings: (values: Settings) => void + footerContent?: (props?: any) => ReactNode + verticalAppBarContent?: (props?: any) => ReactNode + verticalNavMenuContent?: (props?: any) => ReactNode + verticalNavMenuBranding?: (props?: any) => ReactNode + afterVerticalNavMenuContent?: (props?: any) => ReactNode + beforeVerticalNavMenuContent?: (props?: any) => ReactNode +} + +export type BlankLayoutProps = { + children: ReactNode +} diff --git a/core/layouts/utils.ts b/core/layouts/utils.ts new file mode 100644 index 0000000..beb53da --- /dev/null +++ b/core/layouts/utils.ts @@ -0,0 +1,19 @@ +// ** Types +import { NextRouter } from 'next/router' + +/** + * Check for URL queries as well for matching + * Current URL & Item Path + * + * @param item + * @param activeItem + */ +export const handleURLQueries = (router: NextRouter, path: string | undefined): boolean => { + if (Object.keys(router.query).length && path) { + const arr = Object.keys(router.query) + + return router.asPath.includes(path) && router.asPath.includes(router.query[arr[0]] as string) && path !== '/' + } + + return false +} diff --git a/core/styles/libs/react-apexcharts/index.ts b/core/styles/libs/react-apexcharts/index.ts new file mode 100644 index 0000000..f547c6b --- /dev/null +++ b/core/styles/libs/react-apexcharts/index.ts @@ -0,0 +1,103 @@ +// ** MUI imports +import { styled } from '@mui/material/styles' + +const ApexChartWrapper = styled('div')(({ theme }) => ({ + '& .apexcharts-canvas': { + "& line[stroke='transparent']": { + display: 'none' + }, + '& .apexcharts-xaxis > line, & .apexcharts-yaxis > line': { + stroke: theme.palette.divider + }, + '& .apexcharts-xaxis-tick, & .apexcharts-yaxis-tick': { + stroke: theme.palette.divider + }, + '& .apexcharts-tooltip': { + boxShadow: theme.shadows[3], + borderColor: theme.palette.divider, + background: theme.palette.background.paper, + '& .apexcharts-tooltip-title': { + fontWeight: 600, + borderColor: theme.palette.divider, + background: theme.palette.background.paper + }, + '&.apexcharts-theme-dark': { + '& .apexcharts-tooltip-text-label, & .apexcharts-tooltip-text-value': { + color: theme.palette.common.white + } + }, + '& .bar-chart': { + padding: theme.spacing(2, 2.5) + } + }, + '& .apexcharts-xaxistooltip': { + borderColor: theme.palette.divider, + background: theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default, + '& .apexcharts-xaxistooltip-text': { + color: theme.palette.text.primary + }, + '&:after': { + borderBottomColor: theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default + }, + '&:before': { + borderBottomColor: theme.palette.divider + } + }, + '& .apexcharts-yaxistooltip': { + borderColor: theme.palette.divider, + background: theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default, + '& .apexcharts-yaxistooltip-text': { + color: theme.palette.text.primary + }, + '&:after': { + borderLeftColor: theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default + }, + '&:before': { + borderLeftColor: theme.palette.divider + } + }, + '& .apexcharts-text, & .apexcharts-tooltip-text, & .apexcharts-datalabel-label, & .apexcharts-datalabel': { + filter: 'none', + fontWeight: 400, + fill: theme.palette.text.primary, + fontFamily: `${theme.typography.fontFamily} !important` + }, + '& .apexcharts-pie-label': { + filter: 'none', + fill: theme.palette.common.white + }, + '& .apexcharts-pie': { + '& .apexcharts-datalabel-label, .apexcharts-datalabel-value': { + fontSize: '1.5rem' + } + }, + '& .apexcharts-marker': { + boxShadow: 'none' + }, + '& .apexcharts-legend-series': { + margin: `${theme.spacing(0.75, 2)} !important`, + '& .apexcharts-legend-text': { + marginLeft: theme.spacing(0.75), + color: `${theme.palette.text.primary} !important` + } + }, + '& .apexcharts-xcrosshairs, & .apexcharts-ycrosshairs, & .apexcharts-gridline': { + stroke: theme.palette.divider + }, + '& .apexcharts-heatmap-rect': { + stroke: theme.palette.mode === 'light' ? theme.palette.background.paper : theme.palette.background.default + }, + '& .apexcharts-radialbar > g > g:first-of-type .apexcharts-radialbar-area': { + stroke: theme.palette.background.default + }, + '& .apexcharts-radar-series polygon': { + stroke: theme.palette.divider, + fill: theme.palette.background.paper + }, + '& .apexcharts-radar-series line': { + stroke: theme.palette.divider + } + } +})) + +export default ApexChartWrapper diff --git a/core/styles/libs/react-datepicker/index.ts b/core/styles/libs/react-datepicker/index.ts new file mode 100644 index 0000000..2b5571d --- /dev/null +++ b/core/styles/libs/react-datepicker/index.ts @@ -0,0 +1,361 @@ +// ** MUI imports +import { styled } from '@mui/material/styles' +import Box, { BoxProps } from '@mui/material/Box' + +// ** Util Import +import { hexToRGBA } from '../../../../core/utils/hex-to-rgba' + +const DatePickerWrapper = styled(Box)(({ theme }) => { + return { + '& .react-datepicker-popper': { + zIndex: 5 + }, + '& .react-datepicker-wrapper': { + width: '100%' + }, + '& .react-datepicker': { + border: 'none', + boxShadow: theme.shadows[7], + padding: theme.spacing(2, 0), + color: theme.palette.text.primary, + borderRadius: theme.shape.borderRadius, + fontFamily: theme.typography.fontFamily, + backgroundColor: theme.palette.background.paper, + '& .react-datepicker__header': { + padding: 0, + border: 'none', + fontWeight: 'normal', + backgroundColor: theme.palette.background.paper, + '& .react-datepicker__day-name': { + margin: 0 + } + }, + '& .react-datepicker-year-header': { + lineHeight: 2.1, + marginBottom: '0.5rem', + color: theme.palette.text.primary + }, + '& .react-datepicker__triangle': { + display: 'none' + }, + '& > .react-datepicker__navigation': { + top: theme.spacing(3), + '&.react-datepicker__navigation--previous': { + border: 'none', + backgroundImage: `${"url('data:image/svg+xml,%3Csvg xmlns=\\'http://www.w3.org/2000/svg\\' style=\\'width:24px;height:24px\\' viewBox=\\'0 0 24 24\\'%3E%3Cpath fill=\\'currentColor\\' d=\\'M15.41,16.58L10.83,12L15.41,7.41L14,6L8,12L14,18L15.41,16.58Z\\' /%3E%3C/svg%3E')" + .replace('currentColor', theme.palette.text.secondary) + .replace('#', '%23')}`, + height: '24px', + width: '24px', + '& .react-datepicker__navigation-icon': { + display: 'none' + } + }, + '&.react-datepicker__navigation--next': { + border: 'none', + backgroundImage: `${"url('data:image/svg+xml,%3Csvg xmlns=\\'http://www.w3.org/2000/svg\\' style=\\'width:24px;height:24px\\' viewBox=\\'0 0 24 24\\'%3E%3Cpath fill=\\'currentColor\\' d=\\'M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z\\' /%3E%3C/svg%3E')" + .replace('currentColor', theme.palette.text.secondary) + .replace('#', '%23')}`, + height: '24px', + width: '24px', + '& .react-datepicker__navigation-icon': { + display: 'none' + } + }, + '&.react-datepicker__navigation--next--with-time': { + right: '122px' + }, + '&:focus, &:active': { + outline: 0 + } + }, + '& .react-datepicker__current-month': { + lineHeight: 2.1, + fontSize: '1rem', + fontWeight: 'normal', + letterSpacing: '0.15px', + marginBottom: theme.spacing(2), + color: theme.palette.text.primary + }, + '& .react-datepicker__day-name': { + lineHeight: 1.5, + width: '2.25rem', + fontSize: '0.75rem', + letterSpacing: '0.4px', + color: theme.palette.text.secondary + }, + '& .react-datepicker__day': { + margin: 0, + width: '2.25rem', + lineHeight: 2.75, + height: '2.25rem', + borderRadius: '50%', + color: theme.palette.text.primary, + '&.react-datepicker__day--selected, &.react-datepicker__day--keyboard-selected': { + color: theme.palette.common.white, + backgroundColor: `${theme.palette.primary.main} !important` + }, + '&.react-datepicker__day--in-range, &.react-datepicker__day--in-selecting-range': { + borderRadius: 0, + color: theme.palette.primary.main, + backgroundColor: `${hexToRGBA(theme.palette.primary.main, 0.06)} !important`, + '&:empty': { + backgroundColor: 'transparent !important' + } + }, + '&.react-datepicker__day--selected.react-datepicker__day--in-selecting-range.react-datepicker__day--selecting-range-start, &.react-datepicker__day--selected.react-datepicker__day--range-start.react-datepicker__day--in-range, &.react-datepicker__day--range-start': + { + borderTopLeftRadius: '50%', + borderBottomLeftRadius: '50%', + color: theme.palette.common.white, + backgroundColor: `${theme.palette.primary.main} !important` + }, + '&.react-datepicker__day--range-end': { + borderTopRightRadius: '50%', + borderBottomRightRadius: '50%', + color: theme.palette.common.white, + backgroundColor: `${theme.palette.primary.main} !important` + }, + '&:focus, &:active': { + outline: 0 + }, + '&.react-datepicker__day--outside-month': { + height: 'auto' + }, + '&.react-datepicker__day--outside-month, &.react-datepicker__day--disabled:not(.react-datepicker__day--selected)': + { + color: theme.palette.text.disabled, + '&:hover': { + backgroundColor: 'transparent' + } + }, + '&.react-datepicker__day--highlighted, &.react-datepicker__day--highlighted:hover': { + color: theme.palette.success.main, + backgroundColor: hexToRGBA(theme.palette.success.main, 0.12) + }, + '&.react-datepicker__day--today': { + fontWeight: 'normal' + } + }, + '& .react-datepicker__header__dropdown': { + '& .react-datepicker__month-dropdown-container:not(:last-child)': { + marginRight: theme.spacing(8) + }, + '& .react-datepicker__month-dropdown-container, & .react-datepicker__year-dropdown-container': { + marginBottom: theme.spacing(4) + }, + '& .react-datepicker__month-read-view--selected-month, & .react-datepicker__year-read-view--selected-year': { + fontSize: '0.875rem', + marginRight: theme.spacing(1), + color: theme.palette.text.primary + }, + '& .react-datepicker__month-read-view:hover .react-datepicker__month-read-view--down-arrow, & .react-datepicker__year-read-view:hover .react-datepicker__year-read-view--down-arrow': + { + borderTopColor: theme.palette.text.secondary, + borderRightColor: theme.palette.text.secondary + }, + '& .react-datepicker__month-read-view--down-arrow, & .react-datepicker__year-read-view--down-arrow': { + top: 4, + borderTopColor: theme.palette.text.disabled, + borderRightColor: theme.palette.text.disabled + }, + '& .react-datepicker__month-dropdown, & .react-datepicker__year-dropdown': { + paddingTop: theme.spacing(1.5), + paddingBottom: theme.spacing(1.5), + borderColor: theme.palette.divider, + borderRadius: theme.shape.borderRadius, + backgroundColor: theme.palette.background.paper, + boxShadow: theme.palette.mode === 'light' ? theme.shadows[8] : theme.shadows[9] + }, + '& .react-datepicker__month-option, & .react-datepicker__year-option': { + paddingTop: theme.spacing(0.5), + paddingBottom: theme.spacing(0.5), + '&:hover': { + backgroundColor: theme.palette.action.hover + } + }, + '& .react-datepicker__month-option.react-datepicker__month-option--selected_month': { + backgroundColor: hexToRGBA(theme.palette.primary.main, 0.08), + '&:hover': { + backgroundColor: hexToRGBA(theme.palette.primary.main, 0.12) + }, + '& .react-datepicker__month-option--selected': { + display: 'none' + } + }, + '& .react-datepicker__year-option.react-datepicker__year-option--selected_year': { + backgroundColor: hexToRGBA(theme.palette.primary.main, 0.08), + '&:hover': { + backgroundColor: hexToRGBA(theme.palette.primary.main, 0.12) + }, + '& .react-datepicker__year-option--selected': { + display: 'none' + } + }, + '& .react-datepicker__year-option': { + // TODO: Remove some of the following styles for arrow in Year dropdown when react-datepicker give arrows in Year dropdown + '& .react-datepicker__navigation--years-upcoming': { + width: 9, + height: 9, + borderStyle: 'solid', + borderWidth: '3px 3px 0 0', + transform: 'rotate(-45deg)', + borderTopColor: theme.palette.text.disabled, + borderRightColor: theme.palette.text.disabled, + margin: `${theme.spacing(2.75)} auto ${theme.spacing(0)}` + }, + '&:hover .react-datepicker__navigation--years-upcoming': { + borderTopColor: theme.palette.text.secondary, + borderRightColor: theme.palette.text.secondary + }, + '& .react-datepicker__navigation--years-previous': { + width: 9, + height: 9, + borderStyle: 'solid', + borderWidth: '0 0 3px 3px', + transform: 'rotate(-45deg)', + borderLeftColor: theme.palette.text.disabled, + borderBottomColor: theme.palette.text.disabled, + margin: `${theme.spacing(0)} auto ${theme.spacing(2.75)}` + }, + '&:hover .react-datepicker__navigation--years-previous': { + borderLeftColor: theme.palette.text.secondary, + borderBottomColor: theme.palette.text.secondary + } + } + }, + '& .react-datepicker__month': { + marginTop: theme.spacing(3) + }, + [theme.breakpoints.down('sm')]: { + '& .react-datepicker__month': { + marginLeft: 0, + marginRight: 0, + marginBottom: 0 + } + }, + '& .react-datepicker__month, & .react-datepicker__year': { + '& .react-datepicker__month-text, & .react-datepicker__year-text, & .react-datepicker__quarter-text': { + height: '2rem', + alignItems: 'center', + display: 'inline-flex', + justifyContent: 'center', + '&:hover': { + borderRadius: theme.shape.borderRadius + }, + '&:focus, &:active': { + outline: 0 + } + }, + '& .react-datepicker__quarter--selected, & .react-datepicker__year-text--selected, & .react-datepicker__month--selected, & .react-datepicker__quarter-text--keyboard-selected, & .react-datepicker__month-text--keyboard-selected, & .react-datepicker__year-text--keyboard-selected': + { + color: theme.palette.common.white, + borderRadius: theme.shape.borderRadius, + backgroundColor: `${theme.palette.primary.main} !important` + }, + '& .react-datepicker__week-number': { + fontWeight: 600, + color: theme.palette.text.primary + } + }, + '& .react-datepicker__year-wrapper': { + maxWidth: 205, + justifyContent: 'center' + }, + '& .react-datepicker__input-time-container': { + display: 'flex', + alignItems: 'center' + }, + '& .react-datepicker__today-button': { + borderRadius: '1rem', + margin: '0 1rem 0.3rem', + color: theme.palette.common.white, + backgroundColor: theme.palette.primary.main + }, + + // ** Time Picker + '& .react-datepicker__time-container': { + borderLeftColor: theme.palette.divider + }, + '&.react-datepicker--time-only, & .react-datepicker__time-container': { + width: '7rem', + padding: theme.spacing(1.2, 0), + '& .react-datepicker-time__header': { + marginBottom: theme.spacing(3), + color: theme.palette.text.primary, + fontSize: theme.typography.body2.fontSize + }, + + '& .react-datepicker__time': { + background: theme.palette.background.paper, + '& .react-datepicker__time-box .react-datepicker__time-list-item--disabled': { + color: theme.palette.text.disabled + } + }, + + '& .react-datepicker__time-list-item': { + lineHeight: 1.75, + height: 'auto !important', + marginLeft: theme.spacing(3.2), + marginRight: theme.spacing(1.2), + color: theme.palette.text.primary, + borderRadius: theme.shape.borderRadius, + '&:focus, &:active': { + outline: 0 + }, + '&:hover': { + backgroundColor: `${theme.palette.action.hover} !important` + }, + '&.react-datepicker__time-list-item--selected': { + color: `${theme.palette.common.white} !important`, + backgroundColor: `${theme.palette.primary.main} !important` + } + }, + + '& .react-datepicker__time-box': { + width: '100%' + }, + '& .react-datepicker__time-list': { + '&::-webkit-scrollbar': { + width: 8 + }, + + /* Track */ + '&::-webkit-scrollbar-track': { + background: theme.palette.background.paper + }, + + /* Handle */ + '&::-webkit-scrollbar-thumb': { + background: '#aaa', + borderRadius: '10px' + }, + + /* Handle on hover */ + '&::-webkit-scrollbar-thumb:hover': { + background: '#999' + } + } + }, + '&.react-datepicker--time-only .react-datepicker__time-container': { + width: 'calc(7rem - 2px)' + }, + '& .react-datepicker__day:hover, & .react-datepicker__month-text:hover, & .react-datepicker__quarter-text:hover, & .react-datepicker__year-text:hover': + { + backgroundColor: theme.palette.action.hover + } + }, + '& .react-datepicker__close-icon': { + paddingRight: theme.spacing(4), + '&:after': { + width: 'unset', + height: 'unset', + fontSize: '1.5rem', + color: theme.palette.text.primary, + backgroundColor: 'transparent !important' + } + } + } +}) + +export default DatePickerWrapper diff --git a/core/theme/ThemeComponent.tsx b/core/theme/ThemeComponent.tsx new file mode 100644 index 0000000..82b6fb8 --- /dev/null +++ b/core/theme/ThemeComponent.tsx @@ -0,0 +1,60 @@ +// ** React Imports +import { ReactNode } from 'react' + +// ** MUI Imports +import CssBaseline from '@mui/material/CssBaseline' +import GlobalStyles from '@mui/material/GlobalStyles' +import { ThemeProvider, createTheme, responsiveFontSizes } from '@mui/material/styles' + +// ** Type Imports +import { Settings } from '../../core/context/settingsContext' + +// ** Theme Config +import themeConfig from '../../configs/themeConfig' + +// ** Theme Override Imports +import overrides from './overrides' +import typography from './typography' + +// ** Theme +import themeOptions from './ThemeOptions' + +// ** Global Styles +import GlobalStyling from './globalStyles' + +interface Props { + settings: Settings + children: ReactNode +} + +const ThemeComponent = (props: Props) => { + // ** Props + const { settings, children } = props + + // ** Merged ThemeOptions of Core and User + const coreThemeConfig = themeOptions(settings) + + // ** Pass ThemeOptions to CreateTheme Function to create partial theme without component overrides + let theme = createTheme(coreThemeConfig) + + // ** Continue theme creation and pass merged component overrides to CreateTheme function + theme = createTheme(theme, { + components: { ...overrides(theme) }, + typography: { ...typography(theme) } + }) + + // ** Set responsive font sizes to true + if (themeConfig.responsiveFontSizes) { + theme = responsiveFontSizes(theme) + } + + return ( + + + GlobalStyling(theme) as any} /> + {children} + + ) +} + +export default ThemeComponent diff --git a/core/theme/ThemeOptions.ts b/core/theme/ThemeOptions.ts new file mode 100644 index 0000000..8eabb17 --- /dev/null +++ b/core/theme/ThemeOptions.ts @@ -0,0 +1,58 @@ +// ** MUI Theme Provider +import { deepmerge } from '@mui/utils' +import { ThemeOptions } from '@mui/material' + +// ** Type Import +import { Settings } from '../core/context/settingsContext' + +// ** Theme Override Imports +import palette from './palette' +import spacing from './spacing' +import shadows from './shadows' +import breakpoints from './breakpoints' + +const themeOptions = (settings: Settings): ThemeOptions => { + // ** Vars + const { mode, themeColor } = settings + + const themeConfig = { + palette: palette(mode, themeColor), + typography: { + fontFamily: [ + 'Inter', + 'sans-serif', + '-apple-system', + 'BlinkMacSystemFont', + '"Segoe UI"', + 'Roboto', + '"Helvetica Neue"', + 'Arial', + 'sans-serif', + '"Apple Color Emoji"', + '"Segoe UI Emoji"', + '"Segoe UI Symbol"' + ].join(',') + }, + shadows: shadows(mode), + ...spacing, + breakpoints: breakpoints(), + shape: { + borderRadius: 6 + }, + mixins: { + toolbar: { + minHeight: 64 + } + } + } + + return deepmerge(themeConfig, { + palette: { + primary: { + ...themeConfig.palette[themeColor] + } + } + }) +} + +export default themeOptions diff --git a/core/theme/breakpoints/index.ts b/core/theme/breakpoints/index.ts new file mode 100644 index 0000000..2f16351 --- /dev/null +++ b/core/theme/breakpoints/index.ts @@ -0,0 +1,11 @@ +const breakpoints = () => ({ + values: { + xs: 0, + sm: 600, + md: 900, + lg: 1200, + xl: 1536 + } +}) + +export default breakpoints diff --git a/core/theme/globalStyles.ts b/core/theme/globalStyles.ts new file mode 100644 index 0000000..ee097fd --- /dev/null +++ b/core/theme/globalStyles.ts @@ -0,0 +1,47 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const GlobalStyles = (theme: Theme) => { + return { + '.ps__rail-y': { + zIndex: 1, + right: '0 !important', + left: 'auto !important', + '&:hover, &:focus, &.ps--clicking': { + backgroundColor: theme.palette.mode === 'light' ? '#E4E5EB !important' : '#423D5D !important' + }, + '& .ps__thumb-y': { + right: '3px !important', + left: 'auto !important', + backgroundColor: theme.palette.mode === 'light' ? '#C2C4D1 !important' : '#504B6D !important' + }, + '.layout-vertical-nav &': { + '& .ps__thumb-y': { + width: 4, + backgroundColor: theme.palette.mode === 'light' ? '#C2C4D1 !important' : '#504B6D !important' + }, + '&:hover, &:focus, &.ps--clicking': { + backgroundColor: 'transparent !important', + '& .ps__thumb-y': { + width: 6 + } + } + } + }, + + '#nprogress': { + pointerEvents: 'none', + '& .bar': { + left: 0, + top: 0, + height: 3, + width: '100%', + zIndex: 2000, + position: 'fixed', + backgroundColor: theme.palette.primary.main + } + } + } +} + +export default GlobalStyles diff --git a/core/theme/overrides/accordion.ts b/core/theme/overrides/accordion.ts new file mode 100644 index 0000000..a629f7f --- /dev/null +++ b/core/theme/overrides/accordion.ts @@ -0,0 +1,49 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const Accordion = (theme: Theme) => { + return { + MuiAccordion: { + styleOverrides: { + root: { + '&.Mui-disabled': { + backgroundColor: `rgba(${theme.palette.customColors.main}, 0.12)` + }, + '&.Mui-expanded': { + boxShadow: theme.shadows[3] + } + } + } + }, + MuiAccordionSummary: { + styleOverrides: { + root: { + padding: `0 ${theme.spacing(5)}`, + '& + .MuiCollapse-root': { + '& .MuiAccordionDetails-root:first-child': { + paddingTop: 0 + } + } + }, + content: { + margin: `${theme.spacing(2.5)} 0` + }, + expandIconWrapper: { + color: theme.palette.text.secondary + } + } + }, + MuiAccordionDetails: { + styleOverrides: { + root: { + padding: theme.spacing(5), + '& + .MuiAccordionDetails-root': { + paddingTop: 0 + } + } + } + } + } +} + +export default Accordion diff --git a/core/theme/overrides/alerts.ts b/core/theme/overrides/alerts.ts new file mode 100644 index 0000000..7353df8 --- /dev/null +++ b/core/theme/overrides/alerts.ts @@ -0,0 +1,112 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' +import { lighten, darken } from '@mui/material/styles' + +// ** Util Import +import { hexToRGBA } from '../../../core/utils/hex-to-rgba' + +const Alert = (theme: Theme) => { + const getColor = theme.palette.mode === 'light' ? darken : lighten + + return { + MuiAlert: { + styleOverrides: { + root: { + borderRadius: 5, + '& .MuiAlertTitle-root': { + marginBottom: theme.spacing(1.6) + }, + '& a': { + color: 'inherit', + fontWeight: 500 + } + }, + standardSuccess: { + color: getColor(theme.palette.success.main, 0.12), + backgroundColor: hexToRGBA(theme.palette.success.main, 0.12), + '& .MuiAlertTitle-root': { + color: getColor(theme.palette.success.main, 0.12) + }, + '& .MuiAlert-icon': { + color: getColor(theme.palette.success.main, 0.12) + } + }, + standardInfo: { + color: getColor(theme.palette.info.main, 0.12), + backgroundColor: hexToRGBA(theme.palette.info.main, 0.12), + '& .MuiAlertTitle-root': { + color: getColor(theme.palette.info.main, 0.12) + }, + '& .MuiAlert-icon': { + color: getColor(theme.palette.info.main, 0.12) + } + }, + standardWarning: { + color: getColor(theme.palette.warning.main, 0.12), + backgroundColor: hexToRGBA(theme.palette.warning.main, 0.12), + '& .MuiAlertTitle-root': { + color: getColor(theme.palette.warning.main, 0.12) + }, + '& .MuiAlert-icon': { + color: getColor(theme.palette.warning.main, 0.12) + } + }, + standardError: { + color: getColor(theme.palette.error.main, 0.12), + backgroundColor: hexToRGBA(theme.palette.error.main, 0.12), + '& .MuiAlertTitle-root': { + color: getColor(theme.palette.error.main, 0.12) + }, + '& .MuiAlert-icon': { + color: getColor(theme.palette.error.main, 0.12) + } + }, + outlinedSuccess: { + borderColor: theme.palette.success.main, + color: getColor(theme.palette.success.main, 0.12), + '& .MuiAlertTitle-root': { + color: getColor(theme.palette.success.main, 0.12) + }, + '& .MuiAlert-icon': { + color: getColor(theme.palette.success.main, 0.12) + } + }, + outlinedInfo: { + borderColor: theme.palette.info.main, + color: getColor(theme.palette.info.main, 0.12), + '& .MuiAlertTitle-root': { + color: getColor(theme.palette.info.main, 0.12) + }, + '& .MuiAlert-icon': { + color: getColor(theme.palette.info.main, 0.12) + } + }, + outlinedWarning: { + borderColor: theme.palette.warning.main, + color: getColor(theme.palette.warning.main, 0.12), + '& .MuiAlertTitle-root': { + color: getColor(theme.palette.warning.main, 0.12) + }, + '& .MuiAlert-icon': { + color: getColor(theme.palette.warning.main, 0.12) + } + }, + outlinedError: { + borderColor: theme.palette.error.main, + color: getColor(theme.palette.error.main, 0.12), + '& .MuiAlertTitle-root': { + color: getColor(theme.palette.error.main, 0.12) + }, + '& .MuiAlert-icon': { + color: getColor(theme.palette.error.main, 0.12) + } + }, + filled: { + fontWeight: 400 + } + } + } + } +} + +export default Alert diff --git a/core/theme/overrides/avatars.ts b/core/theme/overrides/avatars.ts new file mode 100644 index 0000000..b5c964a --- /dev/null +++ b/core/theme/overrides/avatars.ts @@ -0,0 +1,30 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const Avatar = (theme: Theme) => { + return { + MuiAvatar: { + styleOverrides: { + colorDefault: { + color: theme.palette.text.secondary, + backgroundColor: theme.palette.mode === 'light' ? theme.palette.grey[200] : theme.palette.grey[700] + }, + rounded: { + borderRadius: 5 + } + } + }, + MuiAvatarGroup: { + styleOverrides: { + root: { + justifyContent: 'flex-end', + '.MuiCard-root & .MuiAvatar-root': { + borderColor: theme.palette.background.paper + } + } + } + } + } +} + +export default Avatar diff --git a/core/theme/overrides/backdrop.ts b/core/theme/overrides/backdrop.ts new file mode 100644 index 0000000..a0598cd --- /dev/null +++ b/core/theme/overrides/backdrop.ts @@ -0,0 +1,25 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +// ** Util Import +import { hexToRGBA } from '../../../core/utils/hex-to-rgba' + +const Backdrop = (theme: Theme) => { + return { + MuiBackdrop: { + styleOverrides: { + root: { + backgroundColor: + theme.palette.mode === 'light' + ? `rgba(${theme.palette.customColors.main}, 0.7)` + : hexToRGBA(theme.palette.background.default, 0.7) + }, + invisible: { + backgroundColor: 'transparent' + } + } + } + } +} + +export default Backdrop diff --git a/core/theme/overrides/button.ts b/core/theme/overrides/button.ts new file mode 100644 index 0000000..34fa278 --- /dev/null +++ b/core/theme/overrides/button.ts @@ -0,0 +1,53 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +// ** Theme Config Imports +import themeConfig from '../../../configs/themeConfig' + +const Button = (theme: Theme) => { + return { + MuiButton: { + styleOverrides: { + root: { + fontWeight: 500, + borderRadius: 5, + lineHeight: 1.71, + letterSpacing: '0.3px', + padding: `${theme.spacing(1.875, 3)}` + }, + contained: { + boxShadow: theme.shadows[3], + padding: `${theme.spacing(1.875, 5.5)}` + }, + outlined: { + padding: `${theme.spacing(1.625, 5.25)}` + }, + sizeSmall: { + padding: `${theme.spacing(1, 2.25)}`, + '&.MuiButton-contained': { + padding: `${theme.spacing(1, 3.5)}` + }, + '&.MuiButton-outlined': { + padding: `${theme.spacing(0.75, 3.25)}` + } + }, + sizeLarge: { + padding: `${theme.spacing(2.125, 5.5)}`, + '&.MuiButton-contained': { + padding: `${theme.spacing(2.125, 6.5)}` + }, + '&.MuiButton-outlined': { + padding: `${theme.spacing(1.875, 6.25)}` + } + } + } + }, + MuiButtonBase: { + defaultProps: { + disableRipple: themeConfig.disableRipple + } + } + } +} + +export default Button diff --git a/core/theme/overrides/card.ts b/core/theme/overrides/card.ts new file mode 100644 index 0000000..1259d61 --- /dev/null +++ b/core/theme/overrides/card.ts @@ -0,0 +1,86 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const Card = (theme: Theme) => { + return { + MuiCard: { + styleOverrides: { + root: { + boxShadow: theme.shadows[6], + '& .card-more-options': { + marginTop: theme.spacing(-1), + marginRight: theme.spacing(-3) + } + } + } + }, + MuiCardHeader: { + styleOverrides: { + root: { + padding: theme.spacing(5), + '& + .MuiCardContent-root, & + .MuiCollapse-root .MuiCardContent-root': { + paddingTop: 0 + }, + '& .MuiCardHeader-subheader': { + fontSize: '0.875rem' + } + }, + title: { + lineHeight: 1, + fontWeight: 500, + fontSize: '1.25rem', + letterSpacing: '0.0125em' + }, + action: { + marginTop: 0, + marginRight: 0 + } + } + }, + MuiCardContent: { + styleOverrides: { + root: { + padding: theme.spacing(5), + '& + .MuiCardContent-root': { + paddingTop: 0 + }, + '&:last-of-type': { + paddingBottom: theme.spacing(5) + }, + '& + .MuiCardActions-root': { + paddingTop: 0 + } + } + } + }, + MuiCardActions: { + styleOverrides: { + root: { + padding: theme.spacing(5), + '&.card-action-dense': { + padding: theme.spacing(0, 2.5, 2.5), + '.MuiCard-root .MuiCardMedia-root + &': { + paddingTop: theme.spacing(2.5) + }, + '.MuiCard-root &:first-of-type': { + paddingTop: theme.spacing(5), + paddingBottom: theme.spacing(5), + '& + .MuiCardContent-root': { + paddingTop: 0 + }, + '& + .MuiCardHeader-root': { + paddingTop: 0 + } + } + }, + '& .MuiButton-text': { + paddingLeft: theme.spacing(2.5), + paddingRight: theme.spacing(2.5) + } + } + } + } + } +} + +export default Card diff --git a/core/theme/overrides/chip.ts b/core/theme/overrides/chip.ts new file mode 100644 index 0000000..0951b67 --- /dev/null +++ b/core/theme/overrides/chip.ts @@ -0,0 +1,22 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const Chip = (theme: Theme) => { + return { + MuiChip: { + styleOverrides: { + outlined: { + '&.MuiChip-colorDefault': { + borderColor: `rgba(${theme.palette.customColors.main}, 0.22)` + } + }, + deleteIcon: { + width: 18, + height: 18 + } + } + } + } +} + +export default Chip diff --git a/core/theme/overrides/dateTimePicker.ts b/core/theme/overrides/dateTimePicker.ts new file mode 100644 index 0000000..f7f2aef --- /dev/null +++ b/core/theme/overrides/dateTimePicker.ts @@ -0,0 +1,64 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const DateTimePicker = (theme: Theme) => { + return { + MuiCalendarPicker: { + styleOverrides: { + root: { + '& [role="presentation"]': { + fontWeight: 400, + '& .PrivatePickersFadeTransitionGroup-root + .PrivatePickersFadeTransitionGroup-root > div': { + marginRight: 0 + }, + '& .MuiIconButton-sizeSmall': { + padding: theme.spacing(0.5) + }, + '& + div .MuiIconButton-root:not(.Mui-disabled)': { + color: theme.palette.text.secondary + } + }, + '& .PrivatePickersSlideTransition-root': { + minHeight: 240 + } + } + } + }, + MuiPickersDay: { + styleOverrides: { + root: { + fontSize: '0.875rem' + } + } + }, + MuiClockPicker: { + styleOverrides: { + arrowSwitcher: { + '& .MuiIconButton-root:not(.Mui-disabled)': { + color: theme.palette.text.secondary + }, + '& + div': { + '& > div': { + backgroundColor: + theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default, + '& ~ .MuiIconButton-root span.MuiTypography-caption': { + color: 'inherit' + } + } + } + } + } + }, + MuiMonthPicker: { + styleOverrides: { + root: { + '& > .MuiTypography-root.Mui-selected': { + fontSize: '1rem' + } + } + } + } + } +} + +export default DateTimePicker diff --git a/core/theme/overrides/dialog.ts b/core/theme/overrides/dialog.ts new file mode 100644 index 0000000..1dd784f --- /dev/null +++ b/core/theme/overrides/dialog.ts @@ -0,0 +1,107 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +// ** Util Import +import { hexToRGBA } from '../../../core/utils/hex-to-rgba' + +const Dialog = (theme: Theme) => { + return { + MuiDialog: { + styleOverrides: { + paper: { + boxShadow: theme.shadows[6], + '&:not(.MuiDialog-paperFullScreen)': { + '@media (max-width:599px)': { + margin: theme.spacing(4), + width: `calc(100% - ${theme.spacing(8)})`, + maxWidth: `calc(100% - ${theme.spacing(8)}) !important` + } + }, + '& > .MuiList-root': { + paddingLeft: theme.spacing(1), + paddingRight: theme.spacing(1) + } + } + } + }, + MuiDialogTitle: { + styleOverrides: { + root: { + padding: theme.spacing(5) + } + } + }, + MuiDialogContent: { + styleOverrides: { + root: { + padding: theme.spacing(5), + '& + .MuiDialogContent-root': { + paddingTop: 0 + }, + '& + .MuiDialogActions-root': { + paddingTop: 0 + }, + + // Styling for Mobile Date Picker starts + '& .PrivatePickersToolbar-root': { + padding: theme.spacing(4, 5), + color: theme.palette.primary.contrastText, + backgroundColor: theme.palette.primary.main, + '& .MuiTypography-root': { + color: theme.palette.primary.contrastText + }, + '& span.MuiTypography-overline': { + fontSize: '1rem', + lineHeight: '24px', + letterSpacing: '0.15px' + }, + '& ~ div[class^="css-"] > div[class^="css-"]': { + marginTop: theme.spacing(6), + marginBottom: theme.spacing(6), + '& > div[class^="css-"]': { + backgroundColor: + theme.palette.mode === 'light' ? theme.palette.grey[50] : theme.palette.background.default, + '& ~ .MuiIconButton-root span.MuiTypography-caption': { + color: 'inherit' + } + } + }, + '& .PrivateTimePickerToolbar-hourMinuteLabel': { + alignItems: 'center', + '& > .MuiButton-root span.MuiTypography-root': { + fontWeight: 300, + lineHeight: '72px', + fontSize: '3.75rem', + letterSpacing: '-0.5px' + }, + '& > .MuiTypography-root': { + color: hexToRGBA(theme.palette.primary.contrastText, 0.54), + '& + .MuiButton-root > span.MuiTypography-root': { + color: hexToRGBA(theme.palette.primary.contrastText, 0.54) + } + } + }, + '& .PrivateTimePickerToolbar-ampmSelection span.MuiTypography-root:not(.Mui-selected)': { + color: hexToRGBA(theme.palette.primary.contrastText, 0.54) + } + } + + // Styling for Mobile Date Picker ends + } + } + }, + MuiDialogActions: { + styleOverrides: { + root: { + padding: theme.spacing(5), + '&.dialog-actions-dense': { + padding: theme.spacing(2.5), + paddingTop: 0 + } + } + } + } + } +} + +export default Dialog diff --git a/core/theme/overrides/divider.ts b/core/theme/overrides/divider.ts new file mode 100644 index 0000000..a6084e5 --- /dev/null +++ b/core/theme/overrides/divider.ts @@ -0,0 +1,16 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const Divider = (theme: Theme) => { + return { + MuiDivider: { + styleOverrides: { + root: { + margin: `${theme.spacing(2)} 0` + } + } + } + } +} + +export default Divider diff --git a/core/theme/overrides/index.ts b/core/theme/overrides/index.ts new file mode 100644 index 0000000..4bbfe18 --- /dev/null +++ b/core/theme/overrides/index.ts @@ -0,0 +1,88 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +// ** Overrides Imports +import MuiCard from './card' +import MuiChip from './chip' +import MuiLink from './link' +import MuiList from './list' +import MuiMenu from './menu' +import MuiTabs from './tabs' +import MuiInput from './input' +import MuiPaper from './paper' +import MuiTable from './table' +import MuiAlerts from './alerts' +import MuiButton from './button' +import MuiDialog from './dialog' +import MuiRating from './rating' +import MuiSelect from './select' +import MuiAvatar from './avatars' +import MuiDivider from './divider' +import MuiPopover from './popover' +import MuiTooltip from './tooltip' +import MuiBackdrop from './backdrop' +import MuiSnackbar from './snackbar' +import MuiSwitches from './switches' +import MuiTimeline from './timeline' +import MuiAccordion from './accordion' +import MuiPagination from './pagination' +import MuiTypography from './typography' +import MuiToggleButton from './toggleButton' +import MuiDateTimePicker from './dateTimePicker' + +const Overrides = (theme: Theme) => { + const chip = MuiChip(theme) + const list = MuiList(theme) + const menu = MuiMenu(theme) + const tabs = MuiTabs(theme) + const cards = MuiCard(theme) + const input = MuiInput(theme) + const tables = MuiTable(theme) + const alerts = MuiAlerts(theme) + const button = MuiButton(theme) + const rating = MuiRating(theme) + const avatars = MuiAvatar(theme) + const divider = MuiDivider(theme) + const dialog = MuiDialog(theme) + const popover = MuiPopover(theme) + const tooltip = MuiTooltip(theme) + const backdrop = MuiBackdrop(theme) + const snackbar = MuiSnackbar(theme) + const switches = MuiSwitches(theme) + const timeline = MuiTimeline(theme) + const accordion = MuiAccordion(theme) + const pagination = MuiPagination(theme) + const dateTimePicker = MuiDateTimePicker(theme) + + return Object.assign( + chip, + list, + menu, + tabs, + cards, + input, + alerts, + button, + dialog, + rating, + tables, + avatars, + divider, + MuiLink, + popover, + tooltip, + backdrop, + MuiPaper, + snackbar, + switches, + timeline, + accordion, + MuiSelect, + pagination, + MuiTypography, + dateTimePicker, + MuiToggleButton + ) +} + +export default Overrides diff --git a/core/theme/overrides/input.ts b/core/theme/overrides/input.ts new file mode 100644 index 0000000..5a8c7ab --- /dev/null +++ b/core/theme/overrides/input.ts @@ -0,0 +1,65 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const input = (theme: Theme) => { + return { + MuiInputLabel: { + styleOverrides: { + root: { + color: theme.palette.text.secondary + } + } + }, + MuiInput: { + styleOverrides: { + root: { + '&:before': { + borderBottom: `1px solid rgba(${theme.palette.customColors.main}, 0.22)` + }, + '&:hover:not(.Mui-disabled):before': { + borderBottom: `1px solid rgba(${theme.palette.customColors.main}, 0.32)` + }, + '&.Mui-disabled:before': { + borderBottom: `1px solid ${theme.palette.text.disabled}` + } + } + } + }, + MuiFilledInput: { + styleOverrides: { + root: { + backgroundColor: `rgba(${theme.palette.customColors.main}, 0.04)`, + '&:hover:not(.Mui-disabled)': { + backgroundColor: `rgba(${theme.palette.customColors.main}, 0.08)` + }, + '&:before': { + borderBottom: `1px solid rgba(${theme.palette.customColors.main}, 0.22)` + }, + '&:hover:not(.Mui-disabled):before': { + borderBottom: `1px solid rgba(${theme.palette.customColors.main}, 0.32)` + } + } + } + }, + MuiOutlinedInput: { + styleOverrides: { + root: { + '&:hover:not(.Mui-focused) .MuiOutlinedInput-notchedOutline': { + borderColor: `rgba(${theme.palette.customColors.main}, 0.32)` + }, + '&:hover.Mui-error .MuiOutlinedInput-notchedOutline': { + borderColor: theme.palette.error.main + }, + '& .MuiOutlinedInput-notchedOutline': { + borderColor: `rgba(${theme.palette.customColors.main}, 0.22)` + }, + '&.Mui-disabled .MuiOutlinedInput-notchedOutline': { + borderColor: theme.palette.text.disabled + } + } + } + } + } +} + +export default input diff --git a/core/theme/overrides/link.ts b/core/theme/overrides/link.ts new file mode 100644 index 0000000..e323f80 --- /dev/null +++ b/core/theme/overrides/link.ts @@ -0,0 +1,9 @@ +export default { + MuiLink: { + styleOverrides: { + root: { + textDecoration: 'none' + } + } + } +} diff --git a/core/theme/overrides/list.ts b/core/theme/overrides/list.ts new file mode 100644 index 0000000..cad8827 --- /dev/null +++ b/core/theme/overrides/list.ts @@ -0,0 +1,44 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const List = (theme: Theme) => { + return { + MuiListItemIcon: { + styleOverrides: { + root: { + minWidth: 0, + marginRight: theme.spacing(2.25), + color: theme.palette.text.secondary + } + } + }, + MuiListItemAvatar: { + styleOverrides: { + root: { + minWidth: 0, + marginRight: theme.spacing(4) + } + } + }, + MuiListItemText: { + styleOverrides: { + dense: { + '& .MuiListItemText-primary': { + color: theme.palette.text.primary + } + } + } + }, + MuiListSubheader: { + styleOverrides: { + root: { + fontWeight: 600, + textTransform: 'uppercase', + color: theme.palette.text.primary + } + } + } + } +} + +export default List diff --git a/core/theme/overrides/menu.ts b/core/theme/overrides/menu.ts new file mode 100644 index 0000000..dc13c19 --- /dev/null +++ b/core/theme/overrides/menu.ts @@ -0,0 +1,19 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const Menu = (theme: Theme) => { + return { + MuiMenu: { + styleOverrides: { + root: { + '& .MuiMenu-paper': { + borderRadius: 5, + boxShadow: theme.palette.mode === 'light' ? theme.shadows[8] : theme.shadows[9] + } + } + } + } + } +} + +export default Menu diff --git a/core/theme/overrides/pagination.ts b/core/theme/overrides/pagination.ts new file mode 100644 index 0000000..4df8a4d --- /dev/null +++ b/core/theme/overrides/pagination.ts @@ -0,0 +1,41 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +// ** Util Import +import { hexToRGBA } from '../../../core/utils/hex-to-rgba' + +const Pagination = (theme: Theme) => { + return { + MuiPaginationItem: { + styleOverrides: { + root: { + '&.Mui-selected:not(.Mui-disabled):not(.MuiPaginationItem-textPrimary):not(.MuiPaginationItem-textSecondary):hover': + { + backgroundColor: `rgba(${theme.palette.customColors.main}, 0.12)` + } + }, + outlined: { + borderColor: `rgba(${theme.palette.customColors.main}, 0.22)` + }, + outlinedPrimary: { + '&.Mui-selected': { + backgroundColor: hexToRGBA(theme.palette.primary.main, 0.12), + '&:hover': { + backgroundColor: `${hexToRGBA(theme.palette.primary.main, 0.2)} !important` + } + } + }, + outlinedSecondary: { + '&.Mui-selected': { + backgroundColor: hexToRGBA(theme.palette.secondary.main, 0.12), + '&:hover': { + backgroundColor: `${hexToRGBA(theme.palette.secondary.main, 0.2)} !important` + } + } + } + } + } + } +} + +export default Pagination diff --git a/core/theme/overrides/paper.ts b/core/theme/overrides/paper.ts new file mode 100644 index 0000000..2ea3658 --- /dev/null +++ b/core/theme/overrides/paper.ts @@ -0,0 +1,9 @@ +export default { + MuiPaper: { + styleOverrides: { + root: { + backgroundImage: 'none' + } + } + } +} diff --git a/core/theme/overrides/popover.ts b/core/theme/overrides/popover.ts new file mode 100644 index 0000000..7f9f7f4 --- /dev/null +++ b/core/theme/overrides/popover.ts @@ -0,0 +1,18 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const Popover = (theme: Theme) => { + return { + MuiPopover: { + styleOverrides: { + root: { + '& .MuiPopover-paper': { + boxShadow: theme.shadows[6] + } + } + } + } + } +} + +export default Popover diff --git a/core/theme/overrides/rating.ts b/core/theme/overrides/rating.ts new file mode 100644 index 0000000..0ac1097 --- /dev/null +++ b/core/theme/overrides/rating.ts @@ -0,0 +1,16 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const Rating = (theme: Theme) => { + return { + MuiRating: { + styleOverrides: { + root: { + color: theme.palette.warning.main + } + } + } + } +} + +export default Rating diff --git a/core/theme/overrides/select.ts b/core/theme/overrides/select.ts new file mode 100644 index 0000000..ae2d296 --- /dev/null +++ b/core/theme/overrides/select.ts @@ -0,0 +1,12 @@ +export default { + MuiSelect: { + styleOverrides: { + select: { + minWidth: '6rem !important', + '&.MuiTablePagination-select': { + minWidth: '1rem !important' + } + } + } + } +} diff --git a/core/theme/overrides/snackbar.ts b/core/theme/overrides/snackbar.ts new file mode 100644 index 0000000..9f6784c --- /dev/null +++ b/core/theme/overrides/snackbar.ts @@ -0,0 +1,16 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const Snackbar = (theme: Theme) => { + return { + MuiSnackbarContent: { + styleOverrides: { + root: { + backgroundColor: theme.palette.mode === 'light' ? theme.palette.grey[900] : theme.palette.grey[100] + } + } + } + } +} + +export default Snackbar diff --git a/core/theme/overrides/switches.ts b/core/theme/overrides/switches.ts new file mode 100644 index 0000000..04eb7a4 --- /dev/null +++ b/core/theme/overrides/switches.ts @@ -0,0 +1,18 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const Switch = (theme: Theme) => { + return { + MuiSwitch: { + styleOverrides: { + root: { + '& .MuiSwitch-track': { + backgroundColor: `rgb(${theme.palette.customColors.main})` + } + } + } + } + } +} + +export default Switch diff --git a/core/theme/overrides/table.ts b/core/theme/overrides/table.ts new file mode 100644 index 0000000..8e4cae8 --- /dev/null +++ b/core/theme/overrides/table.ts @@ -0,0 +1,69 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const Table = (theme: Theme) => { + return { + MuiTableContainer: { + styleOverrides: { + root: { + boxShadow: theme.shadows[0], + borderTopColor: theme.palette.divider + } + } + }, + MuiTableHead: { + styleOverrides: { + root: { + textTransform: 'uppercase', + '& .MuiTableCell-head': { + fontSize: '0.75rem', + fontWeight: 600, + letterSpacing: '0.13px' + } + } + } + }, + MuiTableBody: { + styleOverrides: { + root: { + '& .MuiTableCell-body': { + letterSpacing: '0.25px', + color: theme.palette.text.secondary, + '&:not(.MuiTableCell-sizeSmall):not(.MuiTableCell-paddingCheckbox):not(.MuiTableCell-paddingNone)': { + paddingTop: theme.spacing(3.5), + paddingBottom: theme.spacing(3.5) + } + } + } + } + }, + MuiTableRow: { + styleOverrides: { + root: { + '& .MuiTableCell-head:first-child, & .MuiTableCell-root:first-child ': { + paddingLeft: theme.spacing(5) + }, + '& .MuiTableCell-head:last-child, & .MuiTableCell-root:last-child': { + paddingRight: theme.spacing(5) + } + } + } + }, + MuiTableCell: { + styleOverrides: { + root: { + borderBottom: `1px solid ${theme.palette.divider}`, + '& .MuiButton-root': { + textTransform: 'uppercase', + color: theme.palette.text.secondary + } + }, + stickyHeader: { + backgroundColor: theme.palette.customColors.tableHeaderBg + } + } + } + } +} + +export default Table diff --git a/core/theme/overrides/tabs.ts b/core/theme/overrides/tabs.ts new file mode 100644 index 0000000..71a6e2c --- /dev/null +++ b/core/theme/overrides/tabs.ts @@ -0,0 +1,30 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const Tabs = (theme: Theme) => { + return { + MuiTabs: { + styleOverrides: { + vertical: { + minWidth: 130, + marginRight: theme.spacing(4), + borderRight: `1px solid ${theme.palette.divider}`, + '& .MuiTab-root': { + minWidth: 130 + } + } + } + }, + MuiTab: { + styleOverrides: { + textColorSecondary: { + '&.Mui-selected': { + color: theme.palette.text.secondary + } + } + } + } + } +} + +export default Tabs diff --git a/core/theme/overrides/timeline.ts b/core/theme/overrides/timeline.ts new file mode 100644 index 0000000..0035068 --- /dev/null +++ b/core/theme/overrides/timeline.ts @@ -0,0 +1,83 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +// ** Util Import +import { hexToRGBA } from '../../../core/utils/hex-to-rgba' + +const Timeline = (theme: Theme) => { + return { + MuiTimelineItem: { + styleOverrides: { + root: { + '&:not(:last-of-type)': { + '& .MuiTimelineContent-root': { + marginBottom: theme.spacing(4) + } + } + } + } + }, + MuiTimelineConnector: { + styleOverrides: { + root: { + backgroundColor: theme.palette.divider + } + } + }, + MuiTimelineContent: { + styleOverrides: { + root: { + marginTop: theme.spacing(0.5) + } + } + }, + MuiTimelineDot: { + styleOverrides: { + filledPrimary: { + boxShadow: `0 0 0 3px ${hexToRGBA(theme.palette.primary.main, 0.12)}` + }, + filledSecondary: { + boxShadow: `0 0 0 3px ${hexToRGBA(theme.palette.secondary.main, 0.12)}` + }, + filledSuccess: { + boxShadow: `0 0 0 3px ${hexToRGBA(theme.palette.success.main, 0.12)}` + }, + filledError: { + boxShadow: `0 0 0 3px ${hexToRGBA(theme.palette.error.main, 0.12)}` + }, + filledWarning: { + boxShadow: `0 0 0 3px ${hexToRGBA(theme.palette.warning.main, 0.12)}` + }, + filledInfo: { + boxShadow: `0 0 0 3px ${hexToRGBA(theme.palette.info.main, 0.12)}` + }, + filledGrey: { + boxShadow: `0 0 0 3px ${hexToRGBA(theme.palette.grey[400], 0.12)}` + }, + outlinedPrimary: { + '& svg': { color: theme.palette.primary.main } + }, + outlinedSecondary: { + '& svg': { color: theme.palette.secondary.main } + }, + outlinedSuccess: { + '& svg': { color: theme.palette.success.main } + }, + outlinedError: { + '& svg': { color: theme.palette.error.main } + }, + outlinedWarning: { + '& svg': { color: theme.palette.warning.main } + }, + outlinedInfo: { + '& svg': { color: theme.palette.info.main } + }, + outlinedGrey: { + '& svg': { color: theme.palette.grey[500] } + } + } + } + } +} + +export default Timeline diff --git a/core/theme/overrides/toggleButton.ts b/core/theme/overrides/toggleButton.ts new file mode 100644 index 0000000..fa5fd94 --- /dev/null +++ b/core/theme/overrides/toggleButton.ts @@ -0,0 +1,16 @@ +export default { + MuiToggleButtonGroup: { + styleOverrides: { + root: { + borderRadius: 4 + } + } + }, + MuiToggleButton: { + styleOverrides: { + root: { + borderRadius: 4 + } + } + } +} diff --git a/core/theme/overrides/tooltip.ts b/core/theme/overrides/tooltip.ts new file mode 100644 index 0000000..32f0f2b --- /dev/null +++ b/core/theme/overrides/tooltip.ts @@ -0,0 +1,28 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +// ** Util Import +import { hexToRGBA } from '../../../core/utils/hex-to-rgba' + +const Tooltip = (theme: Theme) => { + return { + MuiTooltip: { + styleOverrides: { + tooltip: { + backgroundColor: + theme.palette.mode === 'light' + ? hexToRGBA(theme.palette.grey[900], 0.9) + : hexToRGBA(theme.palette.grey[700], 0.9) + }, + arrow: { + color: + theme.palette.mode === 'light' + ? hexToRGBA(theme.palette.grey[900], 0.9) + : hexToRGBA(theme.palette.grey[700], 0.9) + } + } + } + } +} + +export default Tooltip diff --git a/core/theme/overrides/typography.ts b/core/theme/overrides/typography.ts new file mode 100644 index 0000000..31c659f --- /dev/null +++ b/core/theme/overrides/typography.ts @@ -0,0 +1,16 @@ +// ** MUI Imports +import { Theme } from '@mui/material/styles' + +const Typography = (theme: Theme) => { + return { + MuiTypography: { + styleOverrides: { + gutterBottom: { + marginBottom: theme.spacing(2) + } + } + } + } +} + +export default Typography diff --git a/core/theme/palette/index.ts b/core/theme/palette/index.ts new file mode 100644 index 0000000..79978f7 --- /dev/null +++ b/core/theme/palette/index.ts @@ -0,0 +1,111 @@ +// ** Type Imports +import { PaletteMode } from '@mui/material' +import { ThemeColor } from '../core/layouts/types' + +const DefaultPalette = (mode: PaletteMode, themeColor: ThemeColor) => { + // ** Vars + const lightColor = '58, 53, 65' + const darkColor = '231, 227, 252' + const mainColor = mode === 'light' ? lightColor : darkColor + + const primaryGradient = () => { + if (themeColor === 'primary') { + return '#C6A7FE' + } else if (themeColor === 'secondary') { + return '#9C9FA4' + } else if (themeColor === 'success') { + return '#93DD5C' + } else if (themeColor === 'error') { + return '#FF8C90' + } else if (themeColor === 'warning') { + return '#FFCF5C' + } else { + return '#6ACDFF' + } + } + + return { + customColors: { + main: mainColor, + primaryGradient: primaryGradient(), + tableHeaderBg: mode === 'light' ? '#F9FAFC' : '#3D3759' + }, + common: { + black: '#000', + white: '#FFF' + }, + mode: mode, + primary: { + light: '#9E69FD', + main: '#9155FD', + dark: '#804BDF', + contrastText: '#FFF' + }, + secondary: { + light: '#9C9FA4', + main: '#8A8D93', + dark: '#777B82', + contrastText: '#FFF' + }, + success: { + light: '#6AD01F', + main: '#56CA00', + dark: '#4CB200', + contrastText: '#FFF' + }, + error: { + light: '#FF6166', + main: '#FF4C51', + dark: '#E04347', + contrastText: '#FFF' + }, + warning: { + light: '#FFCA64', + main: '#FFB400', + dark: '#E09E00', + contrastText: '#FFF' + }, + info: { + light: '#32BAFF', + main: '#16B1FF', + dark: '#139CE0', + contrastText: '#FFF' + }, + grey: { + 50: '#FAFAFA', + 100: '#F5F5F5', + 200: '#EEEEEE', + 300: '#E0E0E0', + 400: '#BDBDBD', + 500: '#9E9E9E', + 600: '#757575', + 700: '#616161', + 800: '#424242', + 900: '#212121', + A100: '#D5D5D5', + A200: '#AAAAAA', + A400: '#616161', + A700: '#303030' + }, + text: { + primary: `rgba(${mainColor}, 0.87)`, + secondary: `rgba(${mainColor}, 0.68)`, + disabled: `rgba(${mainColor}, 0.38)` + }, + divider: `rgba(${mainColor}, 0.12)`, + background: { + paper: mode === 'light' ? '#FFF' : '#312D4B', + default: mode === 'light' ? '#F4F5FA' : '#28243D' + }, + action: { + active: `rgba(${mainColor}, 0.54)`, + hover: `rgba(${mainColor}, 0.04)`, + selected: `rgba(${mainColor}, 0.08)`, + disabled: `rgba(${mainColor}, 0.3)`, + disabledBackground: `rgba(${mainColor}, 0.18)`, + focus: `rgba(${mainColor}, 0.12)` + } + } +} + +export default DefaultPalette diff --git a/core/theme/shadows/index.ts b/core/theme/shadows/index.ts new file mode 100644 index 0000000..8ef9c0c --- /dev/null +++ b/core/theme/shadows/index.ts @@ -0,0 +1,63 @@ +// ** Theme Type Import +import { PaletteMode, ThemeOptions } from '@mui/material' + +const Shadows = (mode: PaletteMode): ThemeOptions['shadows'] => { + if (mode === 'light') { + return [ + 'none', + '0px 2px 1px -1px rgba(58, 53, 65, 0.2), 0px 1px 1px 0px rgba(58, 53, 65, 0.14), 0px 1px 3px 0px rgba(58, 53, 65, 0.12)', + '0px 3px 1px -2px rgba(58, 53, 65, 0.2), 0px 2px 2px 0px rgba(58, 53, 65, 0.14), 0px 1px 5px 0px rgba(58, 53, 65, 0.12)', + '0px 4px 8px -4px rgba(58, 53, 65, 0.42)', + '0px 6px 18px -8px rgba(58, 53, 65, 0.56)', + '0px 3px 5px -1px rgba(58, 53, 65, 0.2), 0px 5px 8px 0px rgba(58, 53, 65, 0.14), 0px 1px 14px 0px rgba(58, 53, 65, 0.12)', + '0px 2px 10px 0px rgba(58, 53, 65, 0.1)', + '0px 4px 5px -2px rgba(58, 53, 65, 0.2), 0px 7px 10px 1px rgba(58, 53, 65, 0.14), 0px 2px 16px 1px rgba(58, 53, 65, 0.12)', + '0px 5px 5px -3px rgba(58, 53, 65, 0.2), 0px 8px 10px 1px rgba(58, 53, 65, 0.14), 0px 3px 14px 2px rgba(58, 53, 65, 0.12)', + '0px 5px 6px -3px rgba(58, 53, 65, 0.2), 0px 9px 12px 1px rgba(58, 53, 65, 0.14), 0px 3px 16px 2px rgba(58, 53, 65, 0.12)', + '0px 6px 6px -3px rgba(58, 53, 65, 0.2), 0px 10px 14px 1px rgba(58, 53, 65, 0.14), 0px 4px 18px 3px rgba(58, 53, 65, 0.12)', + '0px 6px 7px -4px rgba(58, 53, 65, 0.2), 0px 11px 15px 1px rgba(58, 53, 65, 0.14), 0px 4px 20px 3px rgba(58, 53, 65, 0.12)', + '0px 7px 8px -4px rgba(58, 53, 65, 0.2), 0px 12px 17px 2px rgba(58, 53, 65, 0.14), 0px 5px 22px 4px rgba(58, 53, 65, 0.12)', + '0px 7px 8px -4px rgba(58, 53, 65, 0.2), 0px 13px 19px 2px rgba(58, 53, 65, 0.14), 0px 5px 24px 4px rgba(58, 53, 65, 0.12)', + '0px 7px 9px -4px rgba(58, 53, 65, 0.2), 0px 14px 21px 2px rgba(58, 53, 65, 0.14), 0px 5px 26px 4px rgba(58, 53, 65, 0.12)', + '0px 8px 9px -5px rgba(58, 53, 65, 0.2), 0px 15px 22px 2px rgba(58, 53, 65, 0.14), 0px 6px 28px 5px rgba(58, 53, 65, 0.12)', + '0px 8px 10px -5px rgba(58, 53, 65, 0.2), 0px 16px 24px 2px rgba(58, 53, 65, 0.14), 0px 6px 30px 5px rgba(58, 53, 65, 0.12)', + '0px 8px 11px -5px rgba(58, 53, 65, 0.2), 0px 17px 26px 2px rgba(58, 53, 65, 0.14), 0px 6px 32px 5px rgba(58, 53, 65, 0.12)', + '0px 9px 11px -5px rgba(58, 53, 65, 0.2), 0px 18px 28px 2px rgba(58, 53, 65, 0.14), 0px 7px 34px 6px rgba(58, 53, 65, 0.12)', + '0px 9px 12px -6px rgba(58, 53, 65, 0.2), 0px 19px 29px 2px rgba(58, 53, 65, 0.14), 0px 7px 36px 6px rgba(58, 53, 65, 0.12)', + '0px 10px 13px -6px rgba(58, 53, 65, 0.2), 0px 20px 31px 3px rgba(58, 53, 65, 0.14), 0px 8px 38px 7px rgba(58, 53, 65, 0.12)', + '0px 10px 13px -6px rgba(58, 53, 65, 0.2), 0px 21px 33px 3px rgba(58, 53, 65, 0.14), 0px 8px 40px 7px rgba(58, 53, 65, 0.12)', + '0px 10px 14px -6px rgba(58, 53, 65, 0.2), 0px 22px 35px 3px rgba(58, 53, 65, 0.14), 0px 8px 42px 7px rgba(58, 53, 65, 0.12)', + '0px 11px 14px -7px rgba(58, 53, 65, 0.2), 0px 23px 36px 3px rgba(58, 53, 65, 0.14), 0px 9px 44px 8px rgba(58, 53, 65, 0.12)', + '0px 11px 15px -7px rgba(58, 53, 65, 0.2), 0px 24px 38px 3px rgba(58, 53, 65, 0.14), 0px 9px 46px 8px rgba(58, 53, 65, 0.12)' + ] + } else { + return [ + 'none', + '0px 2px 1px -1px rgba(19, 17, 32, 0.2), 0px 1px 1px 0px rgba(19, 17, 32, 0.14), 0px 1px 3px 0px rgba(19, 17, 32, 0.12)', + '0px 3px 1px -2px rgba(19, 17, 32, 0.2), 0px 2px 2px 0px rgba(19, 17, 32, 0.14), 0px 1px 5px 0px rgba(19, 17, 32, 0.12)', + '0px 4px 8px -4px rgba(19, 17, 32, 0.42)', + '0px 6px 18px -8px rgba(19, 17, 32, 0.56)', + '0px 3px 5px -1px rgba(19, 17, 32, 0.2), 0px 5px 8px rgba(19, 17, 32, 0.14), 0px 1px 14px rgba(19, 17, 32, 0.12)', + '0px 2px 10px 0px rgba(19, 17, 32, 0.1)', + '0px 4px 5px -2px rgba(19, 17, 32, 0.2), 0px 7px 10px 1px rgba(19, 17, 32, 0.14), 0px 2px 16px 1px rgba(19, 17, 32, 0.12)', + '0px 5px 5px -3px rgba(19, 17, 32, 0.2), 0px 8px 10px 1px rgba(19, 17, 32, 0.14), 0px 3px 14px 2px rgba(19, 17, 32, 0.12)', + '0px 5px 6px -3px rgba(19, 17, 32, 0.2), 0px 9px 12px 1px rgba(19, 17, 32, 0.14), 0px 3px 16px 2px rgba(19, 17, 32, 0.12)', + '0px 6px 6px -3px rgba(19, 17, 32, 0.2), 0px 10px 14px 1px rgba(19, 17, 32, 0.14), 0px 4px 18px 3px rgba(19, 17, 32, 0.12)', + '0px 6px 7px -4px rgba(19, 17, 32, 0.2), 0px 11px 15px 1px rgba(19, 17, 32, 0.14), 0px 4px 20px 3px rgba(19, 17, 32, 0.12)', + '0px 7px 8px -4px rgba(19, 17, 32, 0.2), 0px 12px 17px 2px rgba(19, 17, 32, 0.14), 0px 5px 22px 4px rgba(19, 17, 32, 0.12)', + '0px 7px 8px -4px rgba(19, 17, 32, 0.2), 0px 13px 19px 2px rgba(19, 17, 32, 0.14), 0px 5px 24px 4px rgba(19, 17, 32, 0.12)', + '0px 7px 9px -4px rgba(19, 17, 32, 0.2), 0px 14px 21px 2px rgba(19, 17, 32, 0.14), 0px 5px 26px 4px rgba(19, 17, 32, 0.12)', + '0px 8px 9px -5px rgba(19, 17, 32, 0.2), 0px 15px 22px 2px rgba(19, 17, 32, 0.14), 0px 6px 28px 5px rgba(19, 17, 32, 0.12)', + '0px 8px 10px -5px rgba(19, 17, 32, 0.2), 0px 16px 24px 2px rgba(19, 17, 32, 0.14), 0px 6px 30px 5px rgba(19, 17, 32, 0.12)', + '0px 8px 11px -5px rgba(19, 17, 32, 0.2), 0px 17px 26px 2px rgba(19, 17, 32, 0.14), 0px 6px 32px 5px rgba(19, 17, 32, 0.12)', + '0px 9px 11px -5px rgba(19, 17, 32, 0.2), 0px 18px 28px 2px rgba(19, 17, 32, 0.14), 0px 7px 34px 6px rgba(19, 17, 32, 0.12)', + '0px 9px 12px -6px rgba(19, 17, 32, 0.2), 0px 19px 29px 2px rgba(19, 17, 32, 0.14), 0px 7px 36px 6px rgba(19, 17, 32, 0.12)', + '0px 10px 13px -6px rgba(19, 17, 32, 0.2), 0px 20px 31px 3px rgba(19, 17, 32, 0.14), 0px 8px 38px 7px rgba(19, 17, 32, 0.12)', + '0px 10px 13px -6px rgba(19, 17, 32, 0.2), 0px 21px 33px 3px rgba(19, 17, 32, 0.14), 0px 8px 40px 7px rgba(19, 17, 32, 0.12)', + '0px 10px 14px -6px rgba(19, 17, 32, 0.2), 0px 22px 35px 3px rgba(19, 17, 32, 0.14), 0px 8px 42px 7px rgba(19, 17, 32, 0.12)', + '0px 11px 14px -7px rgba(19, 17, 32, 0.2), 0px 23px 36px 3px rgba(19, 17, 32, 0.14), 0px 9px 44px 8px rgba(19, 17, 32, 0.12)', + '0px 11px 15px -7px rgba(19, 17, 32, 0.2), 0px 24px 38px 3px rgba(19, 17, 32, 0.14), 0px 9px 46px 8px rgba(19, 17, 32, 0.12)' + ] + } +} +export default Shadows diff --git a/core/theme/spacing/index.ts b/core/theme/spacing/index.ts new file mode 100644 index 0000000..c5c010d --- /dev/null +++ b/core/theme/spacing/index.ts @@ -0,0 +1,3 @@ +export default { + spacing: (factor: number) => `${0.25 * factor}rem` +} diff --git a/core/theme/types.ts b/core/theme/types.ts new file mode 100644 index 0000000..8577ed7 --- /dev/null +++ b/core/theme/types.ts @@ -0,0 +1,18 @@ +declare module '@mui/material/styles' { + interface Palette { + customColors: { + main: string + tableHeaderBg: string + primaryGradient: string + } + } + interface PaletteOptions { + customColors?: { + main?: string + tableHeaderBg?: string + primaryGradient?: string + } + } +} + +export {} diff --git a/core/theme/typography/index.ts b/core/theme/typography/index.ts new file mode 100644 index 0000000..f115e13 --- /dev/null +++ b/core/theme/typography/index.ts @@ -0,0 +1,67 @@ +// ** Theme Type Import +import { Theme } from '@mui/material/styles' + +const Typography = (theme: Theme) => { + return { + h1: { + fontWeight: 500, + letterSpacing: '-1.5px', + color: theme.palette.text.primary + }, + h2: { + fontWeight: 500, + letterSpacing: '-0.5px', + color: theme.palette.text.primary + }, + h3: { + fontWeight: 500, + letterSpacing: 0, + color: theme.palette.text.primary + }, + h4: { + fontWeight: 500, + letterSpacing: '0.25px', + color: theme.palette.text.primary + }, + h5: { + fontWeight: 500, + letterSpacing: 0, + color: theme.palette.text.primary + }, + h6: { + letterSpacing: '0.15px', + color: theme.palette.text.primary + }, + subtitle1: { + letterSpacing: '0.15px', + color: theme.palette.text.primary + }, + subtitle2: { + letterSpacing: '0.1px', + color: theme.palette.text.secondary + }, + body1: { + letterSpacing: '0.15px', + color: theme.palette.text.primary + }, + body2: { + lineHeight: 1.5, + letterSpacing: '0.15px', + color: theme.palette.text.secondary + }, + button: { + letterSpacing: '0.3px', + color: theme.palette.text.primary + }, + caption: { + letterSpacing: '0.4px', + color: theme.palette.text.secondary + }, + overline: { + letterSpacing: '1px', + color: theme.palette.text.secondary + } + } +} + +export default Typography diff --git a/core/utils/create-emotion-cache.ts b/core/utils/create-emotion-cache.ts new file mode 100644 index 0000000..264619d --- /dev/null +++ b/core/utils/create-emotion-cache.ts @@ -0,0 +1,5 @@ +import createCache from '@emotion/cache' + +export const createEmotionCache = () => { + return createCache({ key: 'css' }) +} diff --git a/core/utils/hex-to-rgba.ts b/core/utils/hex-to-rgba.ts new file mode 100644 index 0000000..6f726e8 --- /dev/null +++ b/core/utils/hex-to-rgba.ts @@ -0,0 +1,16 @@ +/** + ** Hex color to RGBA color + */ +export const hexToRGBA = (hexCode: string, opacity: number) => { + let hex = hexCode.replace('#', '') + + if (hex.length === 3) { + hex = `${hex[0]}${hex[0]}${hex[1]}${hex[1]}${hex[2]}${hex[2]}` + } + + const r = parseInt(hex.substring(0, 2), 16) + const g = parseInt(hex.substring(2, 4), 16) + const b = parseInt(hex.substring(4, 6), 16) + + return `rgba(${r}, ${g}, ${b}, ${opacity})` +} diff --git a/layouts/UserLayout.tsx b/layouts/UserLayout.tsx new file mode 100644 index 0000000..ce41ff7 --- /dev/null +++ b/layouts/UserLayout.tsx @@ -0,0 +1,77 @@ +// ** React Imports +import { ReactNode } from 'react' + +// ** MUI Imports +import Box from '@mui/material/Box' +import { Theme } from '@mui/material/styles' +import useMediaQuery from '@mui/material/useMediaQuery' + +// ** Layout Imports +// !Do not remove this Layout import +import VerticalLayout from '../core/layouts/VerticalLayout' + +// ** Navigation Imports +import VerticalNavItems from '../navigation/vertical' + +// ** Component Import +import UpgradeToProButton from './components/UpgradeToProButton' +import VerticalAppBarContent from './components/vertical/AppBarContent' + +// ** Hook Import +import { useSettings } from '../core/hooks/useSettings' + +interface Props { + children: ReactNode +} + +const UserLayout = ({ children }: Props) => { + // ** Hooks + const { settings, saveSettings } = useSettings() + + /** + * The below variable will hide the current layout menu at given screen size. + * The menu will be accessible from the Hamburger icon only (Vertical Overlay Menu). + * You can change the screen size from which you want to hide the current layout menu. + * Please refer useMediaQuery() hook: https://mui.com/components/use-media-query/, + * to know more about what values can be passed to this hook. + * ! Do not change this value unless you know what you are doing. It can break the template. + */ + const hidden = useMediaQuery((theme: Theme) => theme.breakpoints.down('lg')) + + const UpgradeToProImg = () => { + return ( + + + + + + ) + } + + return ( + ( + + )} + > + {children} + + ) +} + +export default UserLayout diff --git a/layouts/components/UpgradeToProButton.tsx b/layouts/components/UpgradeToProButton.tsx new file mode 100644 index 0000000..3c48f75 --- /dev/null +++ b/layouts/components/UpgradeToProButton.tsx @@ -0,0 +1,111 @@ +// ** React Import +import { useState } from 'react' + +// ** MUI Imports +import Box from '@mui/material/Box' +import Fade from '@mui/material/Fade' +import Paper from '@mui/material/Paper' +import Button from '@mui/material/Button' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' + +// ** Third Party Imports +import { usePopper } from 'react-popper' + +const BuyNowButton = () => { + // ** States + const [open, setOpen] = useState(false) + const [popperElement, setPopperElement] = useState(null) + const [referenceElement, setReferenceElement] = useState(null) + + const { styles, attributes, update } = usePopper(referenceElement, popperElement, { + placement: 'top-end' + }) + + const handleOpen = () => { + setOpen(true) + update ? update() : null + } + + const handleClose = () => { + setOpen(false) + } + + return ( + theme.spacing(20), bottom: theme => theme.spacing(10), zIndex: 11, position: 'fixed' }} + > + setReferenceElement(e)} + href='https://themeselection.com/products/materio-mui-react-nextjs-admin-template/' + sx={{ + backgroundColor: '#ff3e1d', + boxShadow: '0 1px 20px 1px #ff3e1d', + '&:hover': { + boxShadow: 'none', + backgroundColor: '#e6381a' + } + }} + > + Upgrade To Pro + + + (theme.breakpoints.down('sm') ? 400 : 300) }} + > + + + + + + + Materio - React Admin Template + + + Materio Admin is the most developer friendly & highly customizable Admin Dashboard Template based on MUI + and NextJS. + + + Click on below buttons to explore PRO version. + + + Demo + + + Download + + + + + + + ) +} + +export default BuyNowButton diff --git a/layouts/components/UserIcon.tsx b/layouts/components/UserIcon.tsx new file mode 100644 index 0000000..c91b08f --- /dev/null +++ b/layouts/components/UserIcon.tsx @@ -0,0 +1,29 @@ +// ** React Imports +import { ReactNode } from 'react' + +// ** MUI Imports +import { SvgIconProps } from '@mui/material' + +interface UserIconProps { + iconProps?: SvgIconProps + icon: string | ReactNode +} + +const UserIcon = (props: UserIconProps) => { + // ** Props + const { icon, iconProps } = props + + const IconTag = icon + + let styles + + /* styles = { + color: 'red', + fontSize: '2rem' + } */ + + // @ts-ignore + return +} + +export default UserIcon diff --git a/layouts/components/vertical/AppBarContent.tsx b/layouts/components/vertical/AppBarContent.tsx new file mode 100644 index 0000000..357e757 --- /dev/null +++ b/layouts/components/vertical/AppBarContent.tsx @@ -0,0 +1,79 @@ +// ** MUI Imports +import Box from '@mui/material/Box' +import { Theme } from '@mui/material/styles' +import TextField from '@mui/material/TextField' +import IconButton from '@mui/material/IconButton' +import useMediaQuery from '@mui/material/useMediaQuery' +import InputAdornment from '@mui/material/InputAdornment' +import { + NovuProvider, + PopoverNotificationCenter, + NotificationBell, +} from '@novu/notification-center'; + + +// ** Icons Imports +import Menu from 'mdi-material-ui/Menu' +import Magnify from 'mdi-material-ui/Magnify' + +// ** Type Import +import { Settings } from '../../../core/context/settingsContext' + +// ** Components +import ModeToggler from '../../../core/layouts/components/shared-components/ModeToggler' +import UserDropdown from '../../../core/layouts/components/shared-components/UserDropdown' +import NotificationDropdown from '../../../core/layouts/components/shared-components/NotificationDropdown' + +interface Props { + hidden: boolean + settings: Settings + toggleNavVisibility: () => void + saveSettings: (values: Settings) => void +} + +const AppBarContent = (props: Props) => { + // ** Props + const { hidden, settings, saveSettings, toggleNavVisibility } = props + + // ** Hook + const hiddenSm = useMediaQuery((theme: Theme) => theme.breakpoints.down('sm')) + + return ( + + + {hidden ? ( + + + + ) : null} + + + + ) + }} + /> + + + + + + + {({ unseenCount }) => } + + + + + + ) +} + +export default AppBarContent diff --git a/navigation/vertical/index.ts b/navigation/vertical/index.ts new file mode 100644 index 0000000..37dbac9 --- /dev/null +++ b/navigation/vertical/index.ts @@ -0,0 +1,82 @@ +// ** Icon imports +import Login from 'mdi-material-ui/Login' +import Table from 'mdi-material-ui/Table' +import CubeOutline from 'mdi-material-ui/CubeOutline' +import HomeOutline from 'mdi-material-ui/HomeOutline' +import FormatLetterCase from 'mdi-material-ui/FormatLetterCase' +import AccountCogOutline from 'mdi-material-ui/AccountCogOutline' +import CreditCardOutline from 'mdi-material-ui/CreditCardOutline' +import AccountPlusOutline from 'mdi-material-ui/AccountPlusOutline' +import AlertCircleOutline from 'mdi-material-ui/AlertCircleOutline' +import GoogleCirclesExtended from 'mdi-material-ui/GoogleCirclesExtended' + +// ** Type import +import { VerticalNavItemsType } from '../../core/layouts/types' +import { BankTransfer, PageFirst } from 'mdi-material-ui' +import { DocumentScanner, FileOpen, Settings } from '@mui/icons-material' +import { useState, useEffect } from 'react' + +const navigation = (): VerticalNavItemsType => { + const [isStripeOnboarded, setIsStripeOnboarded] = useState(false); + + const getData = async () => { + const onboardCheckRequest = await fetch('/api/artist/onboarded', { method: "GET" }); + const onboardCheckResponse = await onboardCheckRequest.json(); + setIsStripeOnboarded(onboardCheckResponse["onboarded"]); + } + useEffect(() => { + getData(); + }, []); + + if(isStripeOnboarded){ + + return [ + { + sectionTitle: 'General' + }, + { + title: 'Dashboard', + icon: HomeOutline, + path: '/dashboard' + }, + { + title: 'Account Settings', + icon: Settings, + path: '/artist/settings' + }, + { + sectionTitle: 'Artist' + }, + { + title: 'Payout Portal', + icon: BankTransfer, + path: '/payoutportal' + }, + { + title: 'Page Settings', + icon: DocumentScanner, + path: '/dashboard/artist/pagesettings' + }, + { + title: 'Preview Page', + icon: FileOpen, + path: '/artist/pagesettings' + } + ] + } + else{ + + return [ + { + sectionTitle: 'General' + }, + { + title: 'Dashboard', + icon: HomeOutline, + path: '/dashboard' + } + ] + } +} + +export default navigation diff --git a/package-lock.json b/package-lock.json index 45f72b8..e1af21f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "dependencies": { "@auth0/nextjs-auth0": "^2.2.0", "@emotion/react": "^11.11.3", + "@emotion/server": "^11.11.0", "@emotion/styled": "^11.11.0", "@fontsource/roboto": "^5.0.8", "@lupus-ai/mui-currency-textfield": "^1.0.3", @@ -16,12 +17,20 @@ "@mui/x-data-grid": "^6.19.4", "@mui/x-date-pickers": "^6.19.4", "@novu/notification-center": "^0.22.0", + "apexcharts": "^3.45.2", "dayjs": "^1.11.10", "formidable": "^3.5.1", + "mdi-material-ui": "^7.8.0", + "mui-color-input": "^2.0.2", "next": "latest", + "nprogress": "^0.2.0", "openapi-typescript-fetch": "^1.1.3", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-apexcharts": "^1.4.1", + "react-datepicker": "^6.1.0", + "react-dom": "^18.2.0", + "react-perfect-scrollbar": "^1.5.8", + "react-popper": "^2.3.0" }, "devDependencies": { "@types/node": "^18.0.0", @@ -128,6 +137,14 @@ "node": ">=6.9.0" } }, + "node_modules/@ctrl/tinycolor": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.0.3.tgz", + "integrity": "sha512-e9nEVehVJwkymQpkGhdSNzLT2Lr9UTTby+JePq4Z2SxBbOQjY7pLgSouAaXvfaGQVSAaY0U4eJdwfSDmCbItcw==", + "engines": { + "node": ">=14" + } + }, "node_modules/@emotion/babel-plugin": { "version": "11.11.0", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", @@ -223,6 +240,25 @@ "csstype": "^3.0.2" } }, + "node_modules/@emotion/server": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/server/-/server-11.11.0.tgz", + "integrity": "sha512-6q89fj2z8VBTx9w93kJ5n51hsmtYuFPtZgnc1L8VzRx9ti4EU6EyvF6Nn1H1x3vcCQCF7u2dB2lY4AYJwUW4PA==", + "dependencies": { + "@emotion/utils": "^1.2.1", + "html-tokenize": "^2.0.0", + "multipipe": "^1.0.2", + "through": "^2.3.8" + }, + "peerDependencies": { + "@emotion/css": "^11.0.0-rc.0" + }, + "peerDependenciesMeta": { + "@emotion/css": { + "optional": true + } + } + }, "node_modules/@emotion/sheet": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", @@ -1290,6 +1326,11 @@ "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.8.tgz", "integrity": "sha512-c/hzNDBh7eRF+KbCf+OoZxKbnkpaK/cKp9iLQWqB7muXtM+MtL9SUUH8vCFcLn6dH1Qm05jiexK0ofWY7TfOhQ==" }, + "node_modules/@yr/monotone-cubic-spline": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz", + "integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==" + }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -1321,6 +1362,20 @@ "node": ">=4" } }, + "node_modules/apexcharts": { + "version": "3.45.2", + "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.45.2.tgz", + "integrity": "sha512-PpuM4sJWy70sUh5U1IFn1m1p45MdHSChLUNnqEoUUUHSU2IHZugFrsVNhov1S8Q0cvfdrCRCvdBtHGSs6PSAWQ==", + "dependencies": { + "@yr/monotone-cubic-spline": "^1.0.3", + "svg.draggable.js": "^2.2.2", + "svg.easing.js": "^2.0.0", + "svg.filter.js": "^2.0.2", + "svg.pathmorphing.js": "^0.1.3", + "svg.resize.js": "^1.4.3", + "svg.select.js": "^3.0.1" + } + }, "node_modules/aria-hidden": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.3.tgz", @@ -1375,6 +1430,11 @@ "npm": ">=6" } }, + "node_modules/buffer-from": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", + "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==" + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -1449,6 +1509,11 @@ "validator": "^13.7.0" } }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -1499,6 +1564,11 @@ "node": ">= 0.6" } }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", @@ -1519,6 +1589,15 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, + "node_modules/date-fns": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.3.1.tgz", + "integrity": "sha512-y8e109LYGgoQDveiEBD3DYXKba1jWf5BA8YU1FL5Tvm0BTdEfy54WLCwnuYWZNnzzvALy/QQ4Hov+Q9RVRv+Zw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/dayjs": { "version": "1.11.10", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", @@ -1574,6 +1653,41 @@ "csstype": "^3.0.2" } }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/duplexer2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/engine.io-client": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz", @@ -1716,6 +1830,21 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/html-tokenize": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-tokenize/-/html-tokenize-2.0.1.tgz", + "integrity": "sha512-QY6S+hZ0f5m1WT8WffYN+Hg+xm/w5I8XeUcAq/ZYP5wVC8xbKi4Whhru3FtrAebD5EhBW8rmFzkDI6eCAuFe2w==", + "dependencies": { + "buffer-from": "~0.1.1", + "inherits": "~2.0.1", + "minimist": "~1.2.5", + "readable-stream": "~1.0.27-1", + "through2": "~0.4.1" + }, + "bin": { + "html-tokenize": "bin/cmd.js" + } + }, "node_modules/http-errors": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", @@ -1767,6 +1896,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, "node_modules/joi": { "version": "17.12.1", "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.1.tgz", @@ -1844,6 +1978,15 @@ "node": ">=10" } }, + "node_modules/mdi-material-ui": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/mdi-material-ui/-/mdi-material-ui-7.8.0.tgz", + "integrity": "sha512-jLZKGDZ94Mav4c3r8Cyehqs1dHOviXuIm7vGGCIyxIf4UsWNiveQTCoCrKG2K63IWCHcMg0EfjLFqh4LGaYvoQ==", + "peerDependencies": { + "@mui/material": "^5.0.0 || ^5.0.0-rc.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -1863,11 +2006,49 @@ "node": ">= 0.6" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/mui-color-input": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mui-color-input/-/mui-color-input-2.0.2.tgz", + "integrity": "sha512-jDwoX7j8C6Q10Kr1fRB2HCqm4VS1Q97PZnPd/2sIH3R9B+yNzhyCYFQsJj/CdV1jte2UudUOopLiJkeBZCK5WQ==", + "dependencies": { + "@ctrl/tinycolor": "^4.0.3" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material": "^5.0.0", + "@types/react": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/multipipe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-1.0.2.tgz", + "integrity": "sha512-6uiC9OvY71vzSGX8lZvSqscE7ft9nPupJ8fMjrCNRAUy2LREUW42UL+V/NTrogr6rFgRydUrCX4ZitfpSNkSCQ==", + "dependencies": { + "duplexer2": "^0.1.2", + "object-assign": "^4.1.0" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -1930,6 +2111,11 @@ } } }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -1946,6 +2132,11 @@ "node": ">= 6" } }, + "node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw==" + }, "node_modules/oidc-token-hash": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz", @@ -2026,6 +2217,11 @@ "node": ">=8" } }, + "node_modules/perfect-scrollbar": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.5.tgz", + "integrity": "sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g==" + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -2058,6 +2254,11 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -2089,6 +2290,48 @@ "node": ">=0.10.0" } }, + "node_modules/react-apexcharts": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.4.1.tgz", + "integrity": "sha512-G14nVaD64Bnbgy8tYxkjuXEUp/7h30Q0U33xc3AwtGFijJB9nHqOt1a6eG0WBn055RgRg+NwqbKGtqPxy15d0Q==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "apexcharts": "^3.41.0", + "react": ">=0.13" + } + }, + "node_modules/react-datepicker": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-6.1.0.tgz", + "integrity": "sha512-8uz+hAOpvHqZGvD4Ky1hJ0/tLI4S9B0Gu9LV7LtLxRKXODs/xrxEay0aMVp7AW9iizTeImZh/6aA00fFaRZpJw==", + "dependencies": { + "@floating-ui/react": "^0.26.2", + "classnames": "^2.2.6", + "date-fns": "^3.3.1", + "prop-types": "^15.7.2", + "react-onclickoutside": "^6.13.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17 || ^18", + "react-dom": "^16.9.0 || ^17 || ^18" + } + }, + "node_modules/react-datepicker/node_modules/@floating-ui/react": { + "version": "0.26.9", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.9.tgz", + "integrity": "sha512-p86wynZJVEkEq2BBjY/8p2g3biQ6TlgT4o/3KgFKyTWoJLU1GZ8wpctwRqtkEl2tseYA+kw7dBAIDFcednfI5w==", + "dependencies": { + "@floating-ui/react-dom": "^2.0.8", + "@floating-ui/utils": "^0.2.1", + "tabbable": "^6.0.1" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -2101,6 +2344,11 @@ "react": "^18.2.0" } }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + }, "node_modules/react-infinite-scroll-component": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/react-infinite-scroll-component/-/react-infinite-scroll-component-6.1.0.tgz", @@ -2117,6 +2365,46 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, + "node_modules/react-onclickoutside": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz", + "integrity": "sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==", + "funding": { + "type": "individual", + "url": "https://github.com/Pomax/react-onclickoutside/blob/master/FUNDING.md" + }, + "peerDependencies": { + "react": "^15.5.x || ^16.x || ^17.x || ^18.x", + "react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x" + } + }, + "node_modules/react-perfect-scrollbar": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/react-perfect-scrollbar/-/react-perfect-scrollbar-1.5.8.tgz", + "integrity": "sha512-bQ46m70gp/HJtiBOF3gRzBISSZn8FFGNxznTdmTG8AAwpxG1bJCyn7shrgjEvGSQ5FJEafVEiosY+ccER11OSA==", + "dependencies": { + "perfect-scrollbar": "^1.5.0", + "prop-types": "^15.6.1" + }, + "peerDependencies": { + "react": ">=16.3.3", + "react-dom": ">=16.3.3" + } + }, + "node_modules/react-popper": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", + "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", + "dependencies": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + }, + "peerDependencies": { + "@popperjs/core": "^2.0.0", + "react": "^16.8.0 || ^17 || ^18", + "react-dom": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/react-textarea-autosize": { "version": "8.3.4", "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.3.4.tgz", @@ -2148,6 +2436,17 @@ "react-dom": ">=16.6.0" } }, + "node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", @@ -2182,6 +2481,11 @@ "node": ">=4" } }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/scheduler": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", @@ -2253,6 +2557,11 @@ "node": ">=10.0.0" } }, + "node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + }, "node_modules/styled-jsx": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", @@ -2302,6 +2611,89 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg.draggable.js": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz", + "integrity": "sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==", + "dependencies": { + "svg.js": "^2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.easing.js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/svg.easing.js/-/svg.easing.js-2.0.0.tgz", + "integrity": "sha512-//ctPdJMGy22YoYGV+3HEfHbm6/69LJUTAqI2/5qBvaNHZ9uUFVC82B0Pl299HzgH13rKrBgi4+XyXXyVWWthA==", + "dependencies": { + "svg.js": ">=2.3.x" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.filter.js": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/svg.filter.js/-/svg.filter.js-2.0.2.tgz", + "integrity": "sha512-xkGBwU+dKBzqg5PtilaTb0EYPqPfJ9Q6saVldX+5vCRy31P6TlRCP3U9NxH3HEufkKkpNgdTLBJnmhDHeTqAkw==", + "dependencies": { + "svg.js": "^2.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.js": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz", + "integrity": "sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==" + }, + "node_modules/svg.pathmorphing.js": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz", + "integrity": "sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==", + "dependencies": { + "svg.js": "^2.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.resize.js": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/svg.resize.js/-/svg.resize.js-1.4.3.tgz", + "integrity": "sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==", + "dependencies": { + "svg.js": "^2.6.5", + "svg.select.js": "^2.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.resize.js/node_modules/svg.select.js": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-2.1.2.tgz", + "integrity": "sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==", + "dependencies": { + "svg.js": "^2.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/svg.select.js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-3.0.1.tgz", + "integrity": "sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==", + "dependencies": { + "svg.js": "^2.6.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/tabbable": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", @@ -2315,6 +2707,20 @@ "node": ">=8" } }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/through2": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz", + "integrity": "sha512-45Llu+EwHKtAZYTPPVn3XZHBgakWMN3rokhEv5hu596XP+cNgplMg+Gj+1nmAvj+L0K7+N49zBKx5rah5u0QIQ==", + "dependencies": { + "readable-stream": "~1.0.17", + "xtend": "~2.1.1" + } + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -2429,6 +2835,11 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/validator": { "version": "13.11.0", "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", @@ -2437,6 +2848,14 @@ "node": ">= 0.10" } }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/webfontloader": { "version": "1.6.28", "resolved": "https://registry.npmjs.org/webfontloader/-/webfontloader-1.6.28.tgz", @@ -2475,6 +2894,17 @@ "node": ">=0.4.0" } }, + "node_modules/xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ==", + "dependencies": { + "object-keys": "~0.4.0" + }, + "engines": { + "node": ">=0.4" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index 18dae62..e7c1bb4 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "dependencies": { "@auth0/nextjs-auth0": "^2.2.0", "@emotion/react": "^11.11.3", + "@emotion/server": "^11.11.0", "@emotion/styled": "^11.11.0", "@fontsource/roboto": "^5.0.8", "@lupus-ai/mui-currency-textfield": "^1.0.3", @@ -17,12 +18,20 @@ "@mui/x-data-grid": "^6.19.4", "@mui/x-date-pickers": "^6.19.4", "@novu/notification-center": "^0.22.0", + "apexcharts": "^3.45.2", "dayjs": "^1.11.10", "formidable": "^3.5.1", + "mdi-material-ui": "^7.8.0", + "mui-color-input": "^2.0.2", "next": "latest", + "nprogress": "^0.2.0", "openapi-typescript-fetch": "^1.1.3", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-apexcharts": "^1.4.1", + "react-datepicker": "^6.1.0", + "react-dom": "^18.2.0", + "react-perfect-scrollbar": "^1.5.8", + "react-popper": "^2.3.0" }, "devDependencies": { "@types/node": "^18.0.0", diff --git a/pages/401.tsx b/pages/401.tsx new file mode 100644 index 0000000..d16f0ac --- /dev/null +++ b/pages/401.tsx @@ -0,0 +1,65 @@ +// ** React Imports +import { ReactNode } from 'react' + +// ** Next Import +import Link from 'next/link' + +// ** MUI Components +import Button from '@mui/material/Button' +import { styled } from '@mui/material/styles' +import Typography from '@mui/material/Typography' +import Box, { BoxProps } from '@mui/material/Box' + +// ** Layout Import +import BlankLayout from '../core/layouts/BlankLayout' + +// ** Demo Imports +import FooterIllustrations from '../views/pages/misc/FooterIllustrations' + +// ** Styled Components +const BoxWrapper = styled(Box)(({ theme }) => ({ + [theme.breakpoints.down('md')]: { + width: '90vw' + } +})) + +const Img = styled('img')(({ theme }) => ({ + marginBottom: theme.spacing(10), + [theme.breakpoints.down('lg')]: { + height: 450, + marginTop: theme.spacing(10) + }, + [theme.breakpoints.down('md')]: { + height: 400 + }, + [theme.breakpoints.up('lg')]: { + marginTop: theme.spacing(13) + } +})) + +const Error401 = () => { + return ( + + + + 401 + + You are not authorized! 🔐 + + You don′t have permission to access this page. Go Home! + + + + + Back to Home + + + + + + ) +} + +Error401.getLayout = (page: ReactNode) => {page} + +export default Error401 diff --git a/pages/404.tsx b/pages/404.tsx new file mode 100644 index 0000000..be8940d --- /dev/null +++ b/pages/404.tsx @@ -0,0 +1,74 @@ +// ** React Imports +import { ReactNode } from 'react' + +// ** Next Import +import Link from 'next/link' + +// ** MUI Components +import Button from '@mui/material/Button' +import { styled } from '@mui/material/styles' +import Typography from '@mui/material/Typography' +import Box, { BoxProps } from '@mui/material/Box' + +// ** Layout Import +import BlankLayout from '../core/layouts/BlankLayout' + +// ** Demo Imports +import FooterIllustrations from '../views/pages/misc/FooterIllustrations' + +// ** Styled Components +const BoxWrapper = styled(Box)(({ theme }) => ({ + [theme.breakpoints.down('md')]: { + width: '90vw' + } +})) + +const Img = styled('img')(({ theme }) => ({ + marginBottom: theme.spacing(10), + [theme.breakpoints.down('lg')]: { + height: 450, + marginTop: theme.spacing(10) + }, + [theme.breakpoints.down('md')]: { + height: 400 + }, + [theme.breakpoints.up('lg')]: { + marginTop: theme.spacing(13) + } +})) + +const TreeIllustration = styled('img')(({ theme }) => ({ + left: 0, + bottom: '5rem', + position: 'absolute', + [theme.breakpoints.down('lg')]: { + bottom: 0 + } +})) + +const Error404 = () => { + return ( + + + + 404 + + Page Not Found ⚠️ + + We couldn′t find the page you are looking for. + + + + + Back to Home + + + + } /> + + ) +} + +Error404.getLayout = (page: ReactNode) => {page} + +export default Error404 diff --git a/pages/500.tsx b/pages/500.tsx new file mode 100644 index 0000000..1a8f223 --- /dev/null +++ b/pages/500.tsx @@ -0,0 +1,74 @@ +// ** React Imports +import { ReactNode } from 'react' + +// ** Next Import +import Link from 'next/link' + +// ** MUI Components +import Button from '@mui/material/Button' +import { styled } from '@mui/material/styles' +import Typography from '@mui/material/Typography' +import Box, { BoxProps } from '@mui/material/Box' + +// ** Layout Import +import BlankLayout from '../core/layouts/BlankLayout' + +// ** Demo Imports +import FooterIllustrations from '../views/pages/misc/FooterIllustrations' + +// ** Styled Components +const BoxWrapper = styled(Box)(({ theme }) => ({ + [theme.breakpoints.down('md')]: { + width: '90vw' + } +})) + +const Img = styled('img')(({ theme }) => ({ + marginBottom: theme.spacing(10), + [theme.breakpoints.down('lg')]: { + height: 450, + marginTop: theme.spacing(10) + }, + [theme.breakpoints.down('md')]: { + height: 400 + }, + [theme.breakpoints.up('lg')]: { + marginTop: theme.spacing(13) + } +})) + +const TreeIllustration = styled('img')(({ theme }) => ({ + left: 0, + bottom: '5rem', + position: 'absolute', + [theme.breakpoints.down('lg')]: { + bottom: 0 + } +})) + +const Error500 = () => { + return ( + + + + 500 + + Internal server error 👨🏻💻 + + Oops, something went wrong! + + + + + Back to Home + + + + } /> + + ) +} + +Error500.getLayout = (page: ReactNode) => {page} + +export default Error500 diff --git a/pages/_app.tsx b/pages/_app.tsx index 1140f88..c546666 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -1,38 +1,104 @@ +// ** Next Imports +import Head from 'next/head' +import { Router } from 'next/router' +import type { NextPage } from 'next' +import type { AppProps } from 'next/app' + +// ** Loader Import +import NProgress from 'nprogress' + import { UserProvider } from "@auth0/nextjs-auth0/client"; -import '@fontsource/roboto/300.css'; -import '@fontsource/roboto/400.css'; -import '@fontsource/roboto/500.css'; -import '@fontsource/roboto/700.css'; -import { createTheme } from '@mui/material/styles'; -import { green, purple } from '@mui/material/colors'; -import { ThemeProvider } from "@emotion/react"; +// ** Emotion Imports +import { CacheProvider } from '@emotion/react' +import type { EmotionCache } from '@emotion/cache' -const theme = createTheme({ - palette: { - primary: { - main: '#1D3555', - }, - secondary: { - main: '#E5BEED' - }, - background: { - default: '#3D3E46', - paper: '#FAFAFF' - } - }, -}) +// ** Config Imports +import themeConfig from '../configs/themeConfig' + +// ** Component Imports +import UserLayout from '../layouts/UserLayout' +import ThemeComponent from '../core/theme/ThemeComponent' + +// ** Contexts +import { SettingsConsumer, SettingsProvider } from '../core/context/settingsContext' + +// ** Utils Imports +import { createEmotionCache } from '../core/utils/create-emotion-cache' + +import { useEffect, useState } from 'react' +import { useRouter } from 'next/router'; + +// ** React Perfect Scrollbar Style +import 'react-perfect-scrollbar/dist/css/styles.css' + +// ** Global css styles +import '../styles/globals.css' + +// ** Extend App Props with Emotion +type ExtendedAppProps = AppProps & { + Component: NextPage + emotionCache: EmotionCache +} + +const clientSideEmotionCache = createEmotionCache() + +// ** Pace Loader +if (themeConfig.routingLoader) { + Router.events.on('routeChangeStart', () => { + NProgress.start() + }) + Router.events.on('routeChangeError', () => { + NProgress.done() + }) + Router.events.on('routeChangeComplete', () => { + NProgress.done() + }) +} -export default function App({ Component, pageProps }) { - // optionally pass the 'user' prop from pages that require server-side - // rendering to prepopulate the 'useUser' hook. + +// ** Configure JSS & ClassName +const App = (props: ExtendedAppProps) => { + const { Component, emotionCache = clientSideEmotionCache, pageProps } = props + const { user } = pageProps; + // Variables + const getLayout = Component.getLayout ?? (page => {page}) + + const [isRootPath, setIsRootPath] = useState(true); + + const router = useRouter(); + useEffect(() => { + setIsRootPath(router.pathname === '/'); + }, [router.pathname]); return ( - - - - + + + + {`Request.Box`} + + + + + + + + {({ settings }) => {{ + if (isRootPath) { + return + } else { + return {getLayout()}; + } + }}} + + + - ); + ) } + +export default App \ No newline at end of file diff --git a/pages/_document.tsx b/pages/_document.tsx new file mode 100644 index 0000000..c710172 --- /dev/null +++ b/pages/_document.tsx @@ -0,0 +1,70 @@ +// ** React Import +import { Children } from 'react' + +// ** Next Import +import Document, { Html, Head, Main, NextScript } from 'next/document' + +// ** Emotion Imports +import createEmotionServer from '@emotion/server/create-instance' + +// ** Utils Imports +import { createEmotionCache } from '../core/utils/create-emotion-cache' + +class CustomDocument extends Document { + render() { + return ( + + + + + + + + + + + + + + ) + } +} + +CustomDocument.getInitialProps = async ctx => { + const originalRenderPage = ctx.renderPage + const cache = createEmotionCache() + const { extractCriticalToChunks } = createEmotionServer(cache) + + ctx.renderPage = () => + originalRenderPage({ + enhanceApp: App => props => + ( + + ) + }) + + const initialProps = await Document.getInitialProps(ctx) + const emotionStyles = extractCriticalToChunks(initialProps.html) + const emotionStyleTags = emotionStyles.styles.map(style => { + return ( + + ) + }) + + return { + ...initialProps, + styles: [...Children.toArray(initialProps.styles), ...emotionStyleTags] + } +} + +export default CustomDocument diff --git a/pages/account-settings/index.tsx b/pages/account-settings/index.tsx new file mode 100644 index 0000000..b6cd06c --- /dev/null +++ b/pages/account-settings/index.tsx @@ -0,0 +1,103 @@ +// ** React Imports +import { SyntheticEvent, useState } from 'react' + +// ** MUI Imports +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import TabList from '@mui/lab/TabList' +import TabPanel from '@mui/lab/TabPanel' +import TabContext from '@mui/lab/TabContext' +import { styled } from '@mui/material/styles' +import MuiTab, { TabProps } from '@mui/material/Tab' + +// ** Icons Imports +import AccountOutline from 'mdi-material-ui/AccountOutline' +import LockOpenOutline from 'mdi-material-ui/LockOpenOutline' +import InformationOutline from 'mdi-material-ui/InformationOutline' + +// ** Demo Tabs Imports +import TabInfo from '../../views/account-settings/TabInfo' +import TabAccount from '../../views/account-settings/TabAccount' +import TabSecurity from '../../views/account-settings/TabSecurity' + +// ** Third Party Styles Imports +import 'react-datepicker/dist/react-datepicker.css' + +const Tab = styled(MuiTab)(({ theme }) => ({ + [theme.breakpoints.down('md')]: { + minWidth: 100 + }, + [theme.breakpoints.down('sm')]: { + minWidth: 67 + } +})) + +const TabName = styled('span')(({ theme }) => ({ + lineHeight: 1.71, + fontSize: '0.875rem', + marginLeft: theme.spacing(2.4), + [theme.breakpoints.down('md')]: { + display: 'none' + } +})) + +const AccountSettings = () => { + // ** State + const [value, setValue] = useState('account') + + const handleChange = (event: SyntheticEvent, newValue: string) => { + setValue(newValue) + } + + return ( + + + `1px solid ${theme.palette.divider}` }} + > + + + Account + + } + /> + + + Security + + } + /> + + + Info + + } + /> + + + + + + + + + + + + + + ) +} + +export default AccountSettings diff --git a/pages/advanced/api-profile.tsx b/pages/advanced/api-profile.tsx index 617e86e..348dc39 100644 --- a/pages/advanced/api-profile.tsx +++ b/pages/advanced/api-profile.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; import { useUser } from "@auth0/nextjs-auth0/client"; -import Layout from "../../components/layout"; +import Layout from "../../components/OLd/layout"; const ApiProfile = () => { const { user, isLoading } = useUser(); diff --git a/pages/advanced/ssr-profile.tsx b/pages/advanced/ssr-profile.tsx index e8f02ec..5b829e1 100644 --- a/pages/advanced/ssr-profile.tsx +++ b/pages/advanced/ssr-profile.tsx @@ -1,5 +1,5 @@ import { withPageAuthRequired } from "@auth0/nextjs-auth0"; -import Layout from "../../components/layout"; +import Layout from "../../components/OLd/layout"; import { User } from "../../interfaces"; type ProfileProps = { diff --git a/pages/artist/[id].tsx b/pages/artist/[id].tsx index d7a8094..c2f3fea 100644 --- a/pages/artist/[id].tsx +++ b/pages/artist/[id].tsx @@ -1,4 +1,4 @@ -import Layout from "../../components/layout"; +import Layout from "../../components/OLd/layout"; import { useUser } from "@auth0/nextjs-auth0/client"; import { Box, Grid, Card, CardContent, Typography, List, Button, CircularProgress, Tooltip } from "@mui/material"; import { useState, useEffect } from "react"; diff --git a/pages/artist/[id]/request.tsx b/pages/artist/[id]/request.tsx index 9b72b4c..20a21eb 100644 --- a/pages/artist/[id]/request.tsx +++ b/pages/artist/[id]/request.tsx @@ -1,4 +1,4 @@ -import Layout from "../../../components/layout"; +import Layout from "../../../components/OLd/layout"; import { useUser } from "@auth0/nextjs-auth0/client"; import { Box, Grid, Typography, Button, CircularProgress, TextField} from "@mui/material"; import { useState, useEffect } from "react"; diff --git a/pages/artistDashboard.tsx b/pages/artistDashboard.tsx deleted file mode 100644 index 79106e2..0000000 --- a/pages/artistDashboard.tsx +++ /dev/null @@ -1,201 +0,0 @@ -import { useUser } from "@auth0/nextjs-auth0/client"; -import { useTheme } from '@mui/material/styles'; -import AppBar from '@mui/material/AppBar'; -import Tabs from '@mui/material/Tabs'; -import Tab from '@mui/material/Tab'; -import { Grid, Button, Typography, TextField, Box, CircularProgress, IconButton } from "@mui/material"; -import { useState, useEffect,useRef } from "react"; -import Card from '@mui/material/Card'; -import CardContent from '@mui/material/CardContent'; -import CardActions from '@mui/material/CardActions'; -import { styled } from '@mui/material/styles'; -import SwipeableViews from '../components/swipableView'; -import { DataGrid, GridColDef, GridValueGetterParams } from '@mui/x-data-grid'; - -import ThumbsUpDownIcon from '@mui/icons-material/ThumbsUpDown'; -import EditableArtistPortfolio from "../components/editableArtistPortfolio"; -import Popover from '@mui/material/Popover'; -import ArtistDashboardRequest from "../components/artistDashboardRequest"; - - - - - -const SellerDashoard = (ctx) => { - const { user, isLoading } = useUser(); - const [sellerData, setSellerData] = useState([]); - const [loading, setLoading] = useState(true); // State for loading indicator - const [isOnboarded, setIsOnboarded] = useState(false); - const [onBoardUrl, setOnBoardUrl] = useState(""); - const [tabValue, setTabValue] = useState(1); - - const getData = async () => { - const response = await fetch('/api/artist/profile'); - const sellerProfile = await response.json(); - setSellerData(sellerProfile); - const onboardCheckRequest = await fetch('/api/artist/onboarded', { method: "GET" }); - const onboardCheckResponse = await onboardCheckRequest.json(); - setIsOnboarded(onboardCheckResponse["onboarded"]); - const onboardUrlRequest = await fetch('/api/artist/onboardurl', { method: "GET" }); - const onboardUrlResponse = await onboardUrlRequest.json(); - setOnBoardUrl(onboardUrlResponse["onboardUrl"]); - - setLoading(false); // Once data is fetched, set loading to false - } - - - - const handleChange = (event: React.SyntheticEvent, newValue: number) => { - setTabValue(newValue); - }; - - const handleChangeIndex = (index: number) => { - setTabValue(index); - }; - - interface TabPanelProps { - children?: React.ReactNode; - dir?: string; - index: number; - value: number; - } - - function TabPanel(props: TabPanelProps) { - const { children, value, index, ...other } = props; - - return ( - - {value === index && ( - - {children} - - )} - - ); - } - - function a11yProps(index: number) { - return { - id: `full-width-tab-${index}`, - 'aria-controls': `full-width-tabpanel-${index}`, - }; - } - - - useEffect(() => { - getData(); - }, []); - const theme = useTheme(); - const columns: GridColDef[] = [ - { field: 'requestor', headerName: 'User', width: 150 }, - { field: 'message', headerName: 'Message', width: 280 }, - { field: 'amount', headerName: 'Amount', width: 50 }, - { - field: "action", - headerName: "Action", - sortable: false, - renderCell: (params) => { - - const [anchorEl, setAnchorEl] = useState(null); - const open = Boolean(anchorEl); - const id = open ? 'simple-popover' : undefined; - const buttonRef = useRef(null); - - const accept = (e) => { - return alert("TEST"); - }; - - const decline = (e) => { - return alert("TEST"); - }; - - const handleClick = (e) => { - setAnchorEl(e.currentTarget); - }; - - const handleClose = () => { - setAnchorEl(null); - }; - console.log(params) - return ( - <> - } color="success" onClick={handleClick}> - - Accept - Decline - - > - ) - } - } - ]; - const rows = [ - { id: 1, requestor: 'Snow', message: 'This is a test message!', amount: 35.00 }, - { id: 2, requestor: 'Lannister', message: 'This is a test message!', amount: 42.00 }, - { id: 3, requestor: 'Lannister', message: 'This is a test message!', amount: 45.00 }, - { id: 4, requestor: 'Stark', message: 'This is a test message!', amount: 16.00 }, - { id: 5, requestor: 'Targaryen', message: 'This is a test message!', amount: 150.00 }, - { id: 6, requestor: 'Melisandre', message: "This is a test message!", amount: 150.00 }, - { id: 7, requestor: 'Clifford', message: 'This is a test message!', amount: 44.00 }, - { id: 8, requestor: 'Frances', message: 'This is a test message!', amount: 36.00 }, - { id: 9, requestor: 'Roxie', message: 'This is a test message!', amount: 65.00 }, - ]; - - - - return ( - <> - {loading ? ( // Render loading indicator if loading is true - - - Loading - - - - - ) : ( - - {(Object.keys(sellerData).length > 0 ? ( - <> - - - - Back - - - - - Artist Dashboard - - - - - - - > - - ) : ( - <>> - ))} - - - - )}; ->); -} -export default SellerDashoard; diff --git a/pages/cards/index.tsx b/pages/cards/index.tsx new file mode 100644 index 0000000..8828416 --- /dev/null +++ b/pages/cards/index.tsx @@ -0,0 +1,83 @@ +// ** MUI Imports +import Grid from '@mui/material/Grid' +import Typography from '@mui/material/Typography' + +// ** Demo Components Imports +import CardUser from '../views/cards/CardUser' +import CardImgTop from '../views/cards/CardImgTop' +import CardMobile from '../views/cards/CardMobile' +import CardSupport from '../views/cards/CardSupport' +import CardTwitter from '../views/cards/CardTwitter' +import CardFacebook from '../views/cards/CardFacebook' +import CardLinkedIn from '../views/cards/CardLinkedIn' +import CardAppleWatch from '../views/cards/CardAppleWatch' +import CardMembership from '../views/cards/CardMembership' +import CardInfluencer from '../views/cards/CardInfluencer' +import CardNavigation from '../views/cards/CardNavigation' +import CardWithCollapse from '../views/cards/CardWithCollapse' +import CardVerticalRatings from '../views/cards/CardVerticalRatings' +import CardNavigationCenter from '../views/cards/CardNavigationCenter' +import CardHorizontalRatings from '../views/cards/CardHorizontalRatings' + +const CardBasic = () => { + return ( + + + Basic Cards + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `${theme.spacing(17.5)} !important` }}> + Navigation Cards + + + + + + + + `${theme.spacing(17.5)} !important` }}> + Solid Cards + + + + + + + + + + + + ) +} + +export default CardBasic diff --git a/pages/dashboard/artist/pagesettings.tsx b/pages/dashboard/artist/pagesettings.tsx new file mode 100644 index 0000000..56413d9 --- /dev/null +++ b/pages/dashboard/artist/pagesettings.tsx @@ -0,0 +1,385 @@ +import { withPageAuthRequired } from "@auth0/nextjs-auth0/client"; +import Grid from '@mui/material/Grid'; +import Card from '@mui/material/Card'; +import CardContent from '@mui/material/CardContent'; +import Button from '@mui/material/Button'; +import { Accordion, Typography } from "@mui/material"; +import { useEffect, useState } from "react"; +import Switch from '@mui/material/Switch'; +import Divider from '@mui/material/Divider'; +import TextField from '@mui/material/TextField'; +import { MuiColorInput } from 'mui-color-input' +import { AccordionSummary } from "@mui/material"; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import AccordionDetails from '@mui/material/AccordionDetails'; +import Slider from '@mui/material/Slider'; +import ArtistPortfolio from '../../../components/Old/artistPortfolio'; + +const Profile = () => { + + const [profileData, setSellerProfileData] = useState(null); + + const [backgroundColor, setBackgroundColor] = useState('rgb(126, 115, 115)'); + + const [headerColor, setHeaderColor] = useState('rgb(194, 187, 187)'); + const [headerIsImage, setHeaderImage] = useState(false); + const [headerImageUrl, setHeaderImageUrl] = useState(''); + const [headerText, setHeaderText] = useState('Shop'); + const [headerSize, setHeaderSize] = useState(5); + const headerVariant = [ + 'h6', // Size 1 + 'h5', // Size 2 + 'h4', // Size 3 + 'h3', // Size 4 + 'h2', // Size 5 + 'h1', // Size 6 + ][headerSize - 1] || 'h6'; + + + const [bioColor, setBioColor] = useState('rgb(186, 186, 186)'); + const [bioBgColor, setBioBgColor] = useState('rgb(103, 97, 97)'); + const [bioHeaderColor, setBioHeaderColor] = useState('rgb(255, 255, 255)'); + const [bioHeaderIsImage, setBioHeaderImage] = useState(false); + const [bioHeaderImageUrl, setBioHeaderImageUrl] = useState(''); + const [bioHeaderText, setBioHeaderText] = useState('Biography'); + const [bioHeaderSize, setBioHeaderSize] = useState(3); + const [bioSize, setBioSize] = useState(1); + const bioHeaderVariant = [ + 'h6', // Size 1 + 'h5', // Size 2 + 'h4', // Size 3 + 'h3', // Size 4 + 'h2', // Size 5 + 'h1', // Size 6 + ][bioHeaderSize - 1] || 'h6'; + const bioVariant = [ + 'h6', // Size 1 + 'h5', // Size 2 + 'h4', // Size 3 + 'h3', // Size 4 + 'h2', // Size 5 + 'h1', // Size 6 + ][bioSize - 1] || 'h6'; + + const [portfolioBgColor, setPortfolioBgColor] = useState('rgb(78, 73, 73)'); + const [portfolioColumns, setPotrfolioColumns] = useState(2); + const [portfolioWoven, setPortfolioWoven] = useState(true); + const [portfolioShouldScroll, setPortfolioShouldScroll] = useState(true); + const [portfolioSize, setPortfolioSize] = useState(25); + + const getData = async () => { + const profileResponse = await fetch('/api/artist/profile'); + const sellerProfile = await profileResponse.json(); + setSellerProfileData(sellerProfile); + } + + useEffect(() => { + getData() + }, []); + + const handleBackgroundColorChange = (newValue) => { + setBackgroundColor(newValue) + } + + const handleHeaderTextChange = (e) => { + setHeaderText(e.target.value) + } + + const handleHeaderImageUrl = (e) => { + setHeaderImageUrl(e.target.value) + } + const handleHeaderImageToggle = (e) => { + setHeaderImage(e.target.checked) + }; + + const handleHeaderSize = (e, newValue) => { + setHeaderSize(newValue) + } + + const handleHeaderColorChange = (newValue) => { + setHeaderColor(newValue) + } + + + + const handleBioHeaderTextChange = (e) => { + setBioHeaderText(e.target.value) + } + + const handleBioHeaderImageUrl = (e) => { + setBioHeaderImageUrl(e.target.value) + } + const handleBioHeaderImageToggle = (e) => { + setBioHeaderImage(e.target.checked) + }; + + const handleBioHeaderSize = (e, newValue) => { + setBioHeaderSize(newValue) + } + const handleBioSize = (e, newValue) => { + setBioSize(newValue) + } + + const handleBioHeaderColorChange = (newValue) => { + setBioHeaderColor(newValue) + } + const handleBioColorChange = (newValue) => { + setBioColor(newValue) + } + + const handleBioBgColorChange = (newValue) => { + setBioBgColor(newValue) + } + + + + + const handlePortfolioBgColor = (newValue) => { + setPortfolioBgColor(newValue) + } + + const handlePortfolioColumns = (e, newValue) => { + setPotrfolioColumns(newValue) + } + const handlePortfolioWoven = (e) => { + setPortfolioWoven(e.target.checked) + }; + const handlePortfolioShouldScroll = (e) => { + setPortfolioShouldScroll(e.target.checked) + console.log(portfolioShouldScroll) + }; + const handlePortfolioSize = (e, newValue) => { + setPortfolioSize(newValue) + } + + return ( + + + + + + + + Customize Your Page + + + + + Save + + + + + + + + } + aria-controls="panel1-content" + > + Background + + + + + + + + + + + + + } + aria-controls="panel1-content" + > + Header + + + + + + + + + + + + + + + + + + Text Size + + + + + + + + + + + + } + aria-controls="panel1-content" + > + Biography + + + + + + + + + + + + + + + + + + + + + + + + Header Size + + + + + + + + Text Size + + + + + + + + + + + + } + aria-controls="panel1-content" + > + Portfolio + + + + + + + + + Masonry Layout Enabled + + + + + + + + Columns + + + + + + + + Enable Scrolling + + + + + + + + Max Size + + + + + + + + + + + + + + + + + + + + + + {(headerIsImage) ? ( + + ) : ( + + {headerText} + + )} + + + + + {(bioHeaderIsImage) ? ( + + ) : ( + + {bioHeaderText} + + )} + {(profileData ? profileData["biography"]:null)} + + + + + + + {(portfolioShouldScroll)?( + + {(profileData ? ( + + ):null)} + + ):( + + {(profileData ? ( + + ):null)} + + )} + + + + + + + + + + ); +}; + +// Protected route, checking user authentication client-side.(CSR) +export default withPageAuthRequired(Profile); diff --git a/pages/dashboard/index.tsx b/pages/dashboard/index.tsx new file mode 100644 index 0000000..4f2b944 --- /dev/null +++ b/pages/dashboard/index.tsx @@ -0,0 +1,121 @@ +// ** MUI Imports +import Grid from '@mui/material/Grid' + +// ** Icons Imports +import Poll from 'mdi-material-ui/Poll' +import CurrencyUsd from 'mdi-material-ui/CurrencyUsd' +import HelpCircleOutline from 'mdi-material-ui/HelpCircleOutline' +import BriefcaseVariantOutline from 'mdi-material-ui/BriefcaseVariantOutline' + +// ** Custom Components Imports +import CardStatisticsVerticalComponent from '../../core/components/card-statistics/card-stats-vertical' + + +// ** Styled Component Import +import ApexChartWrapper from '../../core/styles/libs/react-apexcharts' +import { Card, Typography } from '@mui/material' +import { withApiAuthRequired } from "@auth0/nextjs-auth0"; +import { withPageAuthRequired } from '@auth0/nextjs-auth0/client' +import Button from '@mui/material/Button' +import { CardContent } from '@mui/material' +import Onboarding from '../../components/Onboarding' +import { useState } from 'react' +import { useEffect } from 'react' +import { isObject } from 'util' +import Orders from '../../components/Orders' + + + +const Dashboard = () => { + const [profileData, setSellerProfileData] = useState(null); + const [requestData, setSellerRequestData] = useState(null); + + const [onboarding, setOnboarding] = useState(false); + const [onboarded, setOnboarded] = useState(false); + + const setOnboardingTrue = () => { + setOnboarding(true); + } + + const getData = async () => { + const profileResponse = await fetch('/api/artist/profile'); + const sellerProfile = await profileResponse.json(); + setSellerProfileData(sellerProfile); + const requestResponse = await fetch('/api/artist/request'); + const sellerRequest = await requestResponse.json(); + setSellerRequestData(sellerRequest); + setTimeout(getData, 5000); // Poll every 5 seconds (adjust as needed) + + + if(sellerRequest != null && Object.keys(sellerRequest).length>0){ + setOnboarding(true) + } + if(sellerProfile!=null && Object.keys(sellerProfile).length>0 && sellerRequest["accepted"]){ + setOnboarded(true) + } + } + useEffect(() => { + getData(); + }, []); + return ( + + + + + + + + + + + My Orders + + + + + + + + + + + + {( onboarding==true && onboarded==false) ? ( + + + + ):( + (onboarded) ? ( + + + + + + + THIS IS A TEST + + + + + + + ) : ( + + + + + + Become An Artist + + + + + + ) + )} + + + ) +} + +export default withPageAuthRequired(Dashboard) \ No newline at end of file diff --git a/pages/form-layouts/index.tsx b/pages/form-layouts/index.tsx new file mode 100644 index 0000000..980ed9a --- /dev/null +++ b/pages/form-layouts/index.tsx @@ -0,0 +1,37 @@ +// ** MUI Imports +import Grid from '@mui/material/Grid' + +// ** Styled Component +import DatePickerWrapper from '../../core/styles/libs/react-datepicker' + +// ** Demo Components Imports +import FormLayoutsBasic from '../../views/form-layouts/FormLayoutsBasic' +import FormLayoutsIcons from '../../views/form-layouts/FormLayoutsIcons' +import FormLayoutsSeparator from '../../views/form-layouts/FormLayoutsSeparator' +import FormLayoutsAlignment from '../../views/form-layouts/FormLayoutsAlignment' + +// ** Third Party Styles Imports +import 'react-datepicker/dist/react-datepicker.css' + +const FormLayouts = () => { + return ( + + + + + + + + + + + + + + + + + ) +} + +export default FormLayouts diff --git a/pages/icons/index.tsx b/pages/icons/index.tsx new file mode 100644 index 0000000..d5358aa --- /dev/null +++ b/pages/icons/index.tsx @@ -0,0 +1,164 @@ +// ** MUI Imports +import Grid from '@mui/material/Grid' +import Card from '@mui/material/Card' +import Link from '@mui/material/Link' +import Button from '@mui/material/Button' +import Tooltip from '@mui/material/Tooltip' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' + +/** + ** Icons Imports: + * ! You need to import all the icons which come from the API or from your server and then add these icons in 'icons' variable. + * ! If you need all the icons from the library, use "import * as Icon from 'mdi-material-ui'" + * */ +import Abacus from 'mdi-material-ui/Abacus' +import Account from 'mdi-material-ui/Account' +import AbTesting from 'mdi-material-ui/AbTesting' +import AccountBox from 'mdi-material-ui/AccountBox' +import AccountCog from 'mdi-material-ui/AccountCog' +import AbjadArabic from 'mdi-material-ui/AbjadArabic' +import AbjadHebrew from 'mdi-material-ui/AbjadHebrew' +import AbugidaThai from 'mdi-material-ui/AbugidaThai' +import AccessPoint from 'mdi-material-ui/AccessPoint' +import AccountCash from 'mdi-material-ui/AccountCash' +import AccountEdit from 'mdi-material-ui/AccountEdit' +import AccountAlert from 'mdi-material-ui/AccountAlert' +import AccountCheck from 'mdi-material-ui/AccountCheck' +import AccountChild from 'mdi-material-ui/AccountChild' +import AccountClock from 'mdi-material-ui/AccountClock' +import AccountGroup from 'mdi-material-ui/AccountGroup' +import AccountCancel from 'mdi-material-ui/AccountCancel' +import AccountCircle from 'mdi-material-ui/AccountCircle' +import AccessPointOff from 'mdi-material-ui/AccessPointOff' +import AccountConvert from 'mdi-material-ui/AccountConvert' +import AccountDetails from 'mdi-material-ui/AccountDetails' +import AccessPointPlus from 'mdi-material-ui/AccessPointPlus' +import AccessPointCheck from 'mdi-material-ui/AccessPointCheck' +import AccessPointMinus from 'mdi-material-ui/AccessPointMinus' +import AccountArrowLeft from 'mdi-material-ui/AccountArrowLeft' +import AccountCowboyHat from 'mdi-material-ui/AccountCowboyHat' +import AbugidaDevanagari from 'mdi-material-ui/AbugidaDevanagari' +import AccessPointRemove from 'mdi-material-ui/AccessPointRemove' +import AccountArrowRight from 'mdi-material-ui/AccountArrowRight' +import AccountBoxOutline from 'mdi-material-ui/AccountBoxOutline' +import AccountCogOutline from 'mdi-material-ui/AccountCogOutline' +import AccessPointNetwork from 'mdi-material-ui/AccessPointNetwork' +import AccountBoxMultiple from 'mdi-material-ui/AccountBoxMultiple' +import AccountCashOutline from 'mdi-material-ui/AccountCashOutline' +import AccountChildCircle from 'mdi-material-ui/AccountChildCircle' +import AccountEditOutline from 'mdi-material-ui/AccountEditOutline' +import AccountAlertOutline from 'mdi-material-ui/AccountAlertOutline' +import AccountCheckOutline from 'mdi-material-ui/AccountCheckOutline' +import AccountChildOutline from 'mdi-material-ui/AccountChildOutline' +import AccountClockOutline from 'mdi-material-ui/AccountClockOutline' +import AccountCancelOutline from 'mdi-material-ui/AccountCancelOutline' +import AccountCircleOutline from 'mdi-material-ui/AccountCircleOutline' +import AccessPointNetworkOff from 'mdi-material-ui/AccessPointNetworkOff' +import AccountConvertOutline from 'mdi-material-ui/AccountConvertOutline' +import AccountDetailsOutline from 'mdi-material-ui/AccountDetailsOutline' +import AccountArrowLeftOutline from 'mdi-material-ui/AccountArrowLeftOutline' +import AccountArrowRightOutline from 'mdi-material-ui/AccountArrowRightOutline' +import AccountBoxMultipleOutline from 'mdi-material-ui/AccountBoxMultipleOutline' + +const icons = { + Abacus, + Account, + AbTesting, + AccountBox, + AccountCog, + AbjadArabic, + AbjadHebrew, + AbugidaThai, + AccessPoint, + AccountCash, + AccountEdit, + AccountAlert, + AccountCheck, + AccountChild, + AccountClock, + AccountGroup, + AccountCancel, + AccountCircle, + AccessPointOff, + AccountConvert, + AccountDetails, + AccessPointPlus, + AccessPointCheck, + AccessPointMinus, + AccountArrowLeft, + AccountCowboyHat, + AbugidaDevanagari, + AccessPointRemove, + AccountArrowRight, + AccountBoxOutline, + AccountCogOutline, + AccessPointNetwork, + AccountBoxMultiple, + AccountCashOutline, + AccountChildCircle, + AccountEditOutline, + AccountAlertOutline, + AccountCheckOutline, + AccountChildOutline, + AccountClockOutline, + AccountCancelOutline, + AccountCircleOutline, + AccessPointNetworkOff, + AccountConvertOutline, + AccountDetailsOutline, + AccountArrowLeftOutline, + AccountArrowRightOutline, + AccountBoxMultipleOutline +} + +const Icons = () => { + const renderIconGrids = () => { + return Object.keys(icons).map(key => { + const IconTag = icons[key as keyof typeof icons] + + return ( + + + + + + + + + + ) + }) + } + + return ( + + + + + Material Design Icons + + + Material Design Icons from the Community + + + + {renderIconGrids()} + + + + + View All Material Design Icons + + + + ) +} + +export default Icons diff --git a/pages/pages/error/index.tsx b/pages/pages/error/index.tsx new file mode 100644 index 0000000..6a43068 --- /dev/null +++ b/pages/pages/error/index.tsx @@ -0,0 +1,14 @@ +// ** React Imports +import { ReactNode } from 'react' + +// ** Layout Import +import BlankLayout from '../core/layouts/BlankLayout' + +// ** Component Import +import Error404 from '../pages/404' + +const ErrorPage = () => + +ErrorPage.getLayout = (page: ReactNode) => {page} + +export default ErrorPage diff --git a/pages/pages/login/index.tsx b/pages/pages/login/index.tsx new file mode 100644 index 0000000..a9d7065 --- /dev/null +++ b/pages/pages/login/index.tsx @@ -0,0 +1,257 @@ +// ** React Imports +import { ChangeEvent, MouseEvent, ReactNode, useState } from 'react' + +// ** Next Imports +import Link from 'next/link' +import { useRouter } from 'next/router' + +// ** MUI Components +import Box from '@mui/material/Box' +import Button from '@mui/material/Button' +import Divider from '@mui/material/Divider' +import Checkbox from '@mui/material/Checkbox' +import TextField from '@mui/material/TextField' +import InputLabel from '@mui/material/InputLabel' +import Typography from '@mui/material/Typography' +import IconButton from '@mui/material/IconButton' +import CardContent from '@mui/material/CardContent' +import FormControl from '@mui/material/FormControl' +import OutlinedInput from '@mui/material/OutlinedInput' +import { styled, useTheme } from '@mui/material/styles' +import MuiCard, { CardProps } from '@mui/material/Card' +import InputAdornment from '@mui/material/InputAdornment' +import MuiFormControlLabel, { FormControlLabelProps } from '@mui/material/FormControlLabel' + +// ** Icons Imports +import Google from 'mdi-material-ui/Google' +import Github from 'mdi-material-ui/Github' +import Twitter from 'mdi-material-ui/Twitter' +import Facebook from 'mdi-material-ui/Facebook' +import EyeOutline from 'mdi-material-ui/EyeOutline' +import EyeOffOutline from 'mdi-material-ui/EyeOffOutline' + +// ** Configs +import themeConfig from '../configs/themeConfig' + +// ** Layout Import +import BlankLayout from '../core/layouts/BlankLayout' + +// ** Demo Imports +import FooterIllustrationsV1 from '../views/pages/auth/FooterIllustration' + +interface State { + password: string + showPassword: boolean +} + +// ** Styled Components +const Card = styled(MuiCard)(({ theme }) => ({ + [theme.breakpoints.up('sm')]: { width: '28rem' } +})) + +const LinkStyled = styled('a')(({ theme }) => ({ + fontSize: '0.875rem', + textDecoration: 'none', + color: theme.palette.primary.main +})) + +const FormControlLabel = styled(MuiFormControlLabel)(({ theme }) => ({ + '& .MuiFormControlLabel-label': { + fontSize: '0.875rem', + color: theme.palette.text.secondary + } +})) + +const LoginPage = () => { + // ** State + const [values, setValues] = useState({ + password: '', + showPassword: false + }) + + // ** Hook + const theme = useTheme() + const router = useRouter() + + const handleChange = (prop: keyof State) => (event: ChangeEvent) => { + setValues({ ...values, [prop]: event.target.value }) + } + + const handleClickShowPassword = () => { + setValues({ ...values, showPassword: !values.showPassword }) + } + + const handleMouseDownPassword = (event: MouseEvent) => { + event.preventDefault() + } + + return ( + + + `${theme.spacing(12, 9, 7)} !important` }}> + + + + + + + + + + + + + + + + + + {themeConfig.templateName} + + + + + Welcome to {themeConfig.templateName}! 👋🏻 + + Please sign-in to your account and start the adventure + + e.preventDefault()}> + + + Password + + + {values.showPassword ? : } + + + } + /> + + + } label='Remember Me' /> + + e.preventDefault()}>Forgot Password? + + + router.push('/')} + > + Login + + + + New on our platform? + + + + Create an account + + + + or + + + ) => e.preventDefault()}> + + + + + ) => e.preventDefault()}> + + + + + ) => e.preventDefault()}> + (theme.palette.mode === 'light' ? '#272727' : theme.palette.grey[300]) }} + /> + + + + ) => e.preventDefault()}> + + + + + + + + + + ) +} + +LoginPage.getLayout = (page: ReactNode) => {page} + +export default LoginPage diff --git a/pages/pages/register/index.tsx b/pages/pages/register/index.tsx new file mode 100644 index 0000000..f049e1a --- /dev/null +++ b/pages/pages/register/index.tsx @@ -0,0 +1,255 @@ +// ** React Imports +import { useState, Fragment, ChangeEvent, MouseEvent, ReactNode } from 'react' + +// ** Next Imports +import Link from 'next/link' + +// ** MUI Components +import Box from '@mui/material/Box' +import Button from '@mui/material/Button' +import Divider from '@mui/material/Divider' +import Checkbox from '@mui/material/Checkbox' +import TextField from '@mui/material/TextField' +import Typography from '@mui/material/Typography' +import InputLabel from '@mui/material/InputLabel' +import IconButton from '@mui/material/IconButton' +import CardContent from '@mui/material/CardContent' +import FormControl from '@mui/material/FormControl' +import OutlinedInput from '@mui/material/OutlinedInput' +import { styled, useTheme } from '@mui/material/styles' +import MuiCard, { CardProps } from '@mui/material/Card' +import InputAdornment from '@mui/material/InputAdornment' +import MuiFormControlLabel, { FormControlLabelProps } from '@mui/material/FormControlLabel' + +// ** Icons Imports +import Google from 'mdi-material-ui/Google' +import Github from 'mdi-material-ui/Github' +import Twitter from 'mdi-material-ui/Twitter' +import Facebook from 'mdi-material-ui/Facebook' +import EyeOutline from 'mdi-material-ui/EyeOutline' +import EyeOffOutline from 'mdi-material-ui/EyeOffOutline' + +// ** Configs +import themeConfig from '../configs/themeConfig' + +// ** Layout Import +import BlankLayout from '../core/layouts/BlankLayout' + +// ** Demo Imports +import FooterIllustrationsV1 from '../views/pages/auth/FooterIllustration' + +interface State { + password: string + showPassword: boolean +} + +// ** Styled Components +const Card = styled(MuiCard)(({ theme }) => ({ + [theme.breakpoints.up('sm')]: { width: '28rem' } +})) + +const LinkStyled = styled('a')(({ theme }) => ({ + fontSize: '0.875rem', + textDecoration: 'none', + color: theme.palette.primary.main +})) + +const FormControlLabel = styled(MuiFormControlLabel)(({ theme }) => ({ + marginTop: theme.spacing(1.5), + marginBottom: theme.spacing(4), + '& .MuiFormControlLabel-label': { + fontSize: '0.875rem', + color: theme.palette.text.secondary + } +})) + +const RegisterPage = () => { + // ** States + const [values, setValues] = useState({ + password: '', + showPassword: false + }) + + // ** Hook + const theme = useTheme() + + const handleChange = (prop: keyof State) => (event: ChangeEvent) => { + setValues({ ...values, [prop]: event.target.value }) + } + const handleClickShowPassword = () => { + setValues({ ...values, showPassword: !values.showPassword }) + } + const handleMouseDownPassword = (event: MouseEvent) => { + event.preventDefault() + } + + return ( + + + `${theme.spacing(12, 9, 7)} !important` }}> + + + + + + + + + + + + + + + + + + {themeConfig.templateName} + + + + + Adventure starts here 🚀 + + Make your app management easy and fun! + + e.preventDefault()}> + + + + Password + + + {values.showPassword ? : } + + + } + /> + + } + label={ + + I agree to + + ) => e.preventDefault()}> + privacy policy & terms + + + + } + /> + + Sign up + + + + Already have an account? + + + + Sign in instead + + + + or + + + ) => e.preventDefault()}> + + + + + ) => e.preventDefault()}> + + + + + ) => e.preventDefault()}> + (theme.palette.mode === 'light' ? '#272727' : theme.palette.grey[300]) }} + /> + + + + ) => e.preventDefault()}> + + + + + + + + + + ) +} + +RegisterPage.getLayout = (page: ReactNode) => {page} + +export default RegisterPage diff --git a/pages/settings.tsx b/pages/settings.tsx index 815a144..bf08dbe 100644 --- a/pages/settings.tsx +++ b/pages/settings.tsx @@ -1,5 +1,5 @@ import { useUser } from "@auth0/nextjs-auth0/client"; -import Layout from "../components/layout"; +import Layout from "../components/OLd/layout"; import { Grid, Button, Typography, TextField, Box } from "@mui/material"; const Settings = () => { diff --git a/pages/tables/index.tsx b/pages/tables/index.tsx new file mode 100644 index 0000000..9edceb6 --- /dev/null +++ b/pages/tables/index.tsx @@ -0,0 +1,67 @@ +// ** MUI Imports +import Grid from '@mui/material/Grid' +import Link from '@mui/material/Link' +import Card from '@mui/material/Card' +import Typography from '@mui/material/Typography' +import CardHeader from '@mui/material/CardHeader' + +// ** Demo Components Imports +import TableBasic from '../views/tables/TableBasic' +import TableDense from '../views/tables/TableDense' +import TableSpanning from '../views/tables/TableSpanning' +import TableCustomized from '../views/tables/TableCustomized' +import TableCollapsible from '../views/tables/TableCollapsible' +import TableStickyHeader from '../views/tables/TableStickyHeader' + +const MUITable = () => { + return ( + + + + + MUI Tables + + + Tables display sets of data. They can be fully customized + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} + +export default MUITable diff --git a/pages/typography/index.tsx b/pages/typography/index.tsx new file mode 100644 index 0000000..b0413d4 --- /dev/null +++ b/pages/typography/index.tsx @@ -0,0 +1,21 @@ +// ** MUI Imports +import Grid from '@mui/material/Grid' + +// ** Demo Components Imports +import TypographyTexts from '../views/typography/TypographyTexts' +import TypographyHeadings from '../views/typography/TypographyHeadings' + +const TypographyPage = () => { + return ( + + + + + + + + + ) +} + +export default TypographyPage diff --git a/styles/globals.css b/styles/globals.css new file mode 100644 index 0000000..50a6236 --- /dev/null +++ b/styles/globals.css @@ -0,0 +1,24 @@ +html, +body { + min-height: 100%; +} + +#__next { + height: 100%; +} + +code { + font-family: 'Inter', sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', + 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue'; + padding: 0.1rem 0.4rem; + font-size: 90%; + color: #d400ff; + border-radius: 0.1335rem; +} +code:not([class*='language-']):before, +code:not([class*='language-']):after { + content: '`'; +} +code[class*='language-'] { + padding: 0; +} diff --git a/views/account-settings/TabAccount.tsx b/views/account-settings/TabAccount.tsx new file mode 100644 index 0000000..b3d164b --- /dev/null +++ b/views/account-settings/TabAccount.tsx @@ -0,0 +1,165 @@ +// ** React Imports +import { useState, ElementType, ChangeEvent, SyntheticEvent } from 'react' + +// ** MUI Imports +import Box from '@mui/material/Box' +import Grid from '@mui/material/Grid' +import Link from '@mui/material/Link' +import Alert from '@mui/material/Alert' +import Select from '@mui/material/Select' +import { styled } from '@mui/material/styles' +import MenuItem from '@mui/material/MenuItem' +import TextField from '@mui/material/TextField' +import Typography from '@mui/material/Typography' +import InputLabel from '@mui/material/InputLabel' +import AlertTitle from '@mui/material/AlertTitle' +import IconButton from '@mui/material/IconButton' +import CardContent from '@mui/material/CardContent' +import FormControl from '@mui/material/FormControl' +import Button, { ButtonProps } from '@mui/material/Button' + +// ** Icons Imports +import Close from 'mdi-material-ui/Close' + +const ImgStyled = styled('img')(({ theme }) => ({ + width: 120, + height: 120, + marginRight: theme.spacing(6.25), + borderRadius: theme.shape.borderRadius +})) + +const ButtonStyled = styled(Button)(({ theme }) => ({ + [theme.breakpoints.down('sm')]: { + width: '100%', + textAlign: 'center' + } +})) + +const ResetButtonStyled = styled(Button)(({ theme }) => ({ + marginLeft: theme.spacing(4.5), + [theme.breakpoints.down('sm')]: { + width: '100%', + marginLeft: 0, + textAlign: 'center', + marginTop: theme.spacing(4) + } +})) + +const TabAccount = () => { + // ** State + const [openAlert, setOpenAlert] = useState(true) + const [imgSrc, setImgSrc] = useState('/images/avatars/1.png') + + const onChange = (file: ChangeEvent) => { + const reader = new FileReader() + const { files } = file.target as HTMLInputElement + if (files && files.length !== 0) { + reader.onload = () => setImgSrc(reader.result as string) + + reader.readAsDataURL(files[0]) + } + } + + return ( + + + + + + + + + Upload New Photo + + + setImgSrc('/images/avatars/1.png')}> + Reset + + + Allowed PNG or JPEG. Max size of 800K. + + + + + + + + + + + + + + + + + Role + + Admin + Author + Editor + Maintainer + Subscriber + + + + + + Status + + Active + Inactive + Pending + + + + + + + + {openAlert ? ( + + setOpenAlert(false)}> + + + } + > + Your email is not confirmed. Please check your inbox. + e.preventDefault()}> + Resend Confirmation + + + + ) : null} + + + + Save Changes + + + Reset + + + + + + ) +} + +export default TabAccount diff --git a/views/account-settings/TabInfo.tsx b/views/account-settings/TabInfo.tsx new file mode 100644 index 0000000..70f5b34 --- /dev/null +++ b/views/account-settings/TabInfo.tsx @@ -0,0 +1,126 @@ +// ** React Imports +import { forwardRef, useState } from 'react' + +// ** MUI Imports +import Grid from '@mui/material/Grid' +import Radio from '@mui/material/Radio' +import Select from '@mui/material/Select' +import Button from '@mui/material/Button' +import MenuItem from '@mui/material/MenuItem' +import TextField from '@mui/material/TextField' +import FormLabel from '@mui/material/FormLabel' +import InputLabel from '@mui/material/InputLabel' +import RadioGroup from '@mui/material/RadioGroup' +import CardContent from '@mui/material/CardContent' +import FormControl from '@mui/material/FormControl' +import OutlinedInput from '@mui/material/OutlinedInput' +import FormControlLabel from '@mui/material/FormControlLabel' + +// ** Third Party Imports +import DatePicker from 'react-datepicker' + +// ** Styled Components +import DatePickerWrapper from '../../core/styles/libs/react-datepicker' + +const CustomInput = forwardRef((props, ref) => { + return +}) + +const TabInfo = () => { + // ** State + const [date, setDate] = useState(null) + + return ( + + + + + + + + + } + onChange={(date: Date) => setDate(date)} + /> + + + + + + + + + + + Country + + USA + UK + Australia + Germany + + + + + + Languages + } + > + English + French + Spanish + Portuguese + Italian + German + Arabic + + + + + + Gender + + } /> + } /> + } /> + + + + + + Save Changes + + setDate(null)}> + Reset + + + + + + ) +} + +export default TabInfo diff --git a/views/account-settings/TabSecurity.tsx b/views/account-settings/TabSecurity.tsx new file mode 100644 index 0000000..12add6f --- /dev/null +++ b/views/account-settings/TabSecurity.tsx @@ -0,0 +1,222 @@ +// ** React Imports +import { ChangeEvent, MouseEvent, useState } from 'react' + +// ** MUI Imports +import Box from '@mui/material/Box' +import Grid from '@mui/material/Grid' +import Avatar from '@mui/material/Avatar' +import Button from '@mui/material/Button' +import Divider from '@mui/material/Divider' +import InputLabel from '@mui/material/InputLabel' +import IconButton from '@mui/material/IconButton' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' +import FormControl from '@mui/material/FormControl' +import OutlinedInput from '@mui/material/OutlinedInput' +import InputAdornment from '@mui/material/InputAdornment' + +// ** Icons Imports +import EyeOutline from 'mdi-material-ui/EyeOutline' +import KeyOutline from 'mdi-material-ui/KeyOutline' +import EyeOffOutline from 'mdi-material-ui/EyeOffOutline' +import LockOpenOutline from 'mdi-material-ui/LockOpenOutline' + +interface State { + newPassword: string + currentPassword: string + showNewPassword: boolean + confirmNewPassword: string + showCurrentPassword: boolean + showConfirmNewPassword: boolean +} + +const TabSecurity = () => { + // ** States + const [values, setValues] = useState({ + newPassword: '', + currentPassword: '', + showNewPassword: false, + confirmNewPassword: '', + showCurrentPassword: false, + showConfirmNewPassword: false + }) + + // Handle Current Password + const handleCurrentPasswordChange = (prop: keyof State) => (event: ChangeEvent) => { + setValues({ ...values, [prop]: event.target.value }) + } + const handleClickShowCurrentPassword = () => { + setValues({ ...values, showCurrentPassword: !values.showCurrentPassword }) + } + const handleMouseDownCurrentPassword = (event: MouseEvent) => { + event.preventDefault() + } + + // Handle New Password + const handleNewPasswordChange = (prop: keyof State) => (event: ChangeEvent) => { + setValues({ ...values, [prop]: event.target.value }) + } + const handleClickShowNewPassword = () => { + setValues({ ...values, showNewPassword: !values.showNewPassword }) + } + const handleMouseDownNewPassword = (event: MouseEvent) => { + event.preventDefault() + } + + // Handle Confirm New Password + const handleConfirmNewPasswordChange = (prop: keyof State) => (event: ChangeEvent) => { + setValues({ ...values, [prop]: event.target.value }) + } + const handleClickShowConfirmNewPassword = () => { + setValues({ ...values, showConfirmNewPassword: !values.showConfirmNewPassword }) + } + const handleMouseDownConfirmNewPassword = (event: MouseEvent) => { + event.preventDefault() + } + + return ( + + + + + + + + Current Password + + + {values.showCurrentPassword ? : } + + + } + /> + + + + + + New Password + + + {values.showNewPassword ? : } + + + } + /> + + + + + + Confirm New Password + + + {values.showConfirmNewPassword ? : } + + + } + /> + + + + + + + + + + + + + + + + + Two-factor authentication + + + + + + + + + Two factor authentication is not enabled yet. + + + Two-factor authentication adds an additional layer of security to your account by requiring more than just + a password to log in. Learn more. + + + + + + + Save Changes + + setValues({ ...values, currentPassword: '', newPassword: '', confirmNewPassword: '' })} + > + Reset + + + + + ) +} +export default TabSecurity diff --git a/views/cards/CardAppleWatch.tsx b/views/cards/CardAppleWatch.tsx new file mode 100644 index 0000000..16690fb --- /dev/null +++ b/views/cards/CardAppleWatch.tsx @@ -0,0 +1,28 @@ +// ** MUI Imports +import Card from '@mui/material/Card' +import Button from '@mui/material/Button' +import CardMedia from '@mui/material/CardMedia' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' + +const CardAppleWatch = () => { + return ( + + + `${theme.spacing(3, 5.25, 4)} !important` }}> + + Apple Watch + + $249.40 + + 3.1GHz 6-core 10th-generation Intel Core i5 processor, Turbo Boost up to 4.5GHz + + + + Add To Cart + + + ) +} + +export default CardAppleWatch diff --git a/views/cards/CardFacebook.tsx b/views/cards/CardFacebook.tsx new file mode 100644 index 0000000..f486c03 --- /dev/null +++ b/views/cards/CardFacebook.tsx @@ -0,0 +1,55 @@ +// ** MUI Imports +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import Avatar from '@mui/material/Avatar' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' + +// ** Icons Imports +import Heart from 'mdi-material-ui/Heart' +import Facebook from 'mdi-material-ui/Facebook' +import ShareVariant from 'mdi-material-ui/ShareVariant' + +const CardFacebook = () => { + return ( + + `${theme.spacing(3.25, 5, 4.5)} !important` }}> + + + Facebook Card + + + You’ve read about the importance of being courageous, rebellious and imaginative. These are all vital + ingredients in an effective. + + + + + + Eugene Clarke + + + + + + + 3.2k + + + + + + 49 + + + + + + + ) +} + +export default CardFacebook diff --git a/views/cards/CardHorizontalRatings.tsx b/views/cards/CardHorizontalRatings.tsx new file mode 100644 index 0000000..a5d3cd5 --- /dev/null +++ b/views/cards/CardHorizontalRatings.tsx @@ -0,0 +1,80 @@ +// ** MUI Imports +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import Rating from '@mui/material/Rating' +import Button from '@mui/material/Button' +import { styled } from '@mui/material/styles' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' +import CardActions from '@mui/material/CardActions' +import Grid, { GridProps } from '@mui/material/Grid' + +// Styled Grid component +const StyledGrid1 = styled(Grid)(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'flex-start', + [theme.breakpoints.down('md')]: { + paddingTop: '0 !important' + }, + '& .MuiCardContent-root': { + padding: theme.spacing(3, 4.75), + [theme.breakpoints.down('md')]: { + paddingTop: 0 + } + } +})) + +// Styled Grid component +const StyledGrid2 = styled(Grid)(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + [theme.breakpoints.up('md')]: { + paddingLeft: '0 !important' + }, + [theme.breakpoints.down('md')]: { + order: -1 + } +})) + +// Styled component for the image +const Img = styled('img')(({ theme }) => ({ + height: '11rem', + borderRadius: theme.shape.borderRadius +})) + +const CardHorizontalRatings = () => { + return ( + + + + + + Stumptown Roasters + + + + 5 Star | 98 reviews + + + Before there was a United States of America, there were coffee houses, because how are you supposed to + build. + + + + Location + Reviews + + + + + + + + + + ) +} + +export default CardHorizontalRatings diff --git a/views/cards/CardImgTop.tsx b/views/cards/CardImgTop.tsx new file mode 100644 index 0000000..0d191df --- /dev/null +++ b/views/cards/CardImgTop.tsx @@ -0,0 +1,24 @@ +// ** MUI Imports +import Card from '@mui/material/Card' +import CardMedia from '@mui/material/CardMedia' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' + +const CardImgTop = () => { + return ( + + + + + Influencing The Influencer + + + Cancun is back, better than ever! Over a hundred Mexico resorts have reopened and the state tourism minister + predicts Cancun will draw as many visitors in 2006 as it did two years ago. + + + + ) +} + +export default CardImgTop diff --git a/views/cards/CardInfluencer.tsx b/views/cards/CardInfluencer.tsx new file mode 100644 index 0000000..5538e7d --- /dev/null +++ b/views/cards/CardInfluencer.tsx @@ -0,0 +1,31 @@ +// ** MUI Imports +import Card from '@mui/material/Card' +import Button from '@mui/material/Button' +import Typography from '@mui/material/Typography' +import CardHeader from '@mui/material/CardHeader' +import CardContent from '@mui/material/CardContent' +import CardActions from '@mui/material/CardActions' + +const CardInfluencer = () => { + return ( + + + + + Computers have become ubiquitous in almost every facet of our lives. At work, desk jockeys spend hours in + front of their desktops, while delivery people scan bar codes with handhelds and workers in the field stay in + touch. + + + If you’re in the market for new desktops, notebooks, or PDAs, there are a myriad of choices. Here’s a rundown + of some of the best systems available. + + + + Read More + + + ) +} + +export default CardInfluencer diff --git a/views/cards/CardLinkedIn.tsx b/views/cards/CardLinkedIn.tsx new file mode 100644 index 0000000..49b8fae --- /dev/null +++ b/views/cards/CardLinkedIn.tsx @@ -0,0 +1,55 @@ +// ** MUI Imports +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import Avatar from '@mui/material/Avatar' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' + +// ** Icons Imports +import Heart from 'mdi-material-ui/Heart' +import Linkedin from 'mdi-material-ui/Linkedin' +import ShareVariant from 'mdi-material-ui/ShareVariant' + +const CardLinkedIn = () => { + return ( + + `${theme.spacing(3.25, 5, 4.5)} !important` }}> + + + LinkedIn Card + + + With the Internet spreading like wildfire and reaching every part of our daily life, more and more traffic is + directed. + + + + + + Anne Burke + + + + + + + 1.1k + + + + + + 67 + + + + + + + ) +} + +export default CardLinkedIn diff --git a/views/cards/CardMembership.tsx b/views/cards/CardMembership.tsx new file mode 100644 index 0000000..796ee46 --- /dev/null +++ b/views/cards/CardMembership.tsx @@ -0,0 +1,104 @@ +// ** MUI Imports +import Card from '@mui/material/Card' +import Grid from '@mui/material/Grid' +import Button from '@mui/material/Button' +import Divider from '@mui/material/Divider' +import { styled } from '@mui/material/styles' +import Typography from '@mui/material/Typography' +import Box, { BoxProps } from '@mui/material/Box' +import CardContent from '@mui/material/CardContent' + +// ** Icons Imports +import TrendingUp from 'mdi-material-ui/TrendingUp' +import StarOutline from 'mdi-material-ui/StarOutline' +import AccountOutline from 'mdi-material-ui/AccountOutline' +import LockOpenOutline from 'mdi-material-ui/LockOpenOutline' + +// Styled Box component +const StyledBox = styled(Box)(({ theme }) => ({ + [theme.breakpoints.up('sm')]: { + borderRight: `1px solid ${theme.palette.divider}` + } +})) + +const CardMembership = () => { + return ( + + + + `${theme.spacing(3.25, 5.75, 6.25)} !important` }}> + + Lifetime Membership + + + Here, I focus on a range of items and features that we use in life without giving them a second thought + such as Coca Cola, body muscles and holding ones own breath. Though, most of these notes are not + fundamentally necessary, they are such that you can use them for a good laugh, at a drinks party or for + picking up women or men. + + + + + + + + Full Access + + + + 15 Members + + + + + + + Access all Features + + + + Lifetime Free Update + + + + + + + `${theme.spacing(18, 5, 16)} !important` + }} + > + + + $ + + 899 + + USD + + + 5 Tips For Offshore + Software Development + + Contact Now + + + + + + ) +} + +export default CardMembership diff --git a/views/cards/CardMobile.tsx b/views/cards/CardMobile.tsx new file mode 100644 index 0000000..0f00dc3 --- /dev/null +++ b/views/cards/CardMobile.tsx @@ -0,0 +1,128 @@ +// ** React Imports +import { MouseEvent, useState } from 'react' + +// ** MUI Imports +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import Menu from '@mui/material/Menu' +import Button from '@mui/material/Button' +import MenuItem from '@mui/material/MenuItem' +import { styled } from '@mui/material/styles' +import Typography from '@mui/material/Typography' +import IconButton from '@mui/material/IconButton' +import CardContent from '@mui/material/CardContent' +import CardActions from '@mui/material/CardActions' +import Grid, { GridProps } from '@mui/material/Grid' + +// ** Icons Imports +import Twitter from 'mdi-material-ui/Twitter' +import CartPlus from 'mdi-material-ui/CartPlus' +import Facebook from 'mdi-material-ui/Facebook' +import Linkedin from 'mdi-material-ui/Linkedin' +import GooglePlus from 'mdi-material-ui/GooglePlus' +import ShareVariant from 'mdi-material-ui/ShareVariant' + +// Styled Grid component +const StyledGrid = styled(Grid)(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + [theme.breakpoints.down('md')]: { + borderBottom: `1px solid ${theme.palette.divider}` + }, + [theme.breakpoints.up('md')]: { + borderRight: `1px solid ${theme.palette.divider}` + } +})) + +const CardMobile = () => { + // ** State + const [anchorEl, setAnchorEl] = useState(null) + + const open = Boolean(anchorEl) + + const handleClick = (event: MouseEvent) => { + setAnchorEl(event.currentTarget) + } + const handleClose = () => { + setAnchorEl(null) + } + + return ( + + + + + + + + + + + Apple iPhone 11 Pro + + + Apple iPhone 11 Pro smartphone. Announced Sep 2019. Features 5.8″ display Apple A13 Bionic + + + Price:{' '} + + $899 + + + + + + + + Add to Card + + + + + + + + + + + + + + + + + + + + + + + + ) +} + +export default CardMobile diff --git a/views/cards/CardNavigation.tsx b/views/cards/CardNavigation.tsx new file mode 100644 index 0000000..587ab9e --- /dev/null +++ b/views/cards/CardNavigation.tsx @@ -0,0 +1,67 @@ +// ** React Imports +import { SyntheticEvent, useState } from 'react' + +// ** MUI Imports +import Tab from '@mui/material/Tab' +import Card from '@mui/material/Card' +import TabList from '@mui/lab/TabList' +import TabPanel from '@mui/lab/TabPanel' +import Button from '@mui/material/Button' +import TabContext from '@mui/lab/TabContext' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' + +const CardNavigation = () => { + // ** State + const [value, setValue] = useState('1') + + const handleChange = (event: SyntheticEvent, newValue: string) => { + setValue(newValue) + } + + return ( + + + + + + + + + + + Header One + + + Pudding tiramisu caramels. Gingerbread gummies danish chocolate bar toffee marzipan. Wafer wafer cake + powder danish oat cake. + + Button One + + + + Header Two + + + Dragée chupa chups soufflé cheesecake jelly tootsie roll cupcake marzipan. Carrot cake sweet roll gummi + bears caramels jelly beans. + + Button Two + + + + Header Three + + + Icing cake macaroon macaroon jelly chocolate bar. Chupa chups dessert dessert soufflé chocolate bar + jujubes gummi bears lollipop. + + Button Three + + + + + ) +} + +export default CardNavigation diff --git a/views/cards/CardNavigationCenter.tsx b/views/cards/CardNavigationCenter.tsx new file mode 100644 index 0000000..ee341ea --- /dev/null +++ b/views/cards/CardNavigationCenter.tsx @@ -0,0 +1,67 @@ +// ** React Imports +import { SyntheticEvent, useState } from 'react' + +// ** MUI Imports +import Tab from '@mui/material/Tab' +import Card from '@mui/material/Card' +import TabList from '@mui/lab/TabList' +import TabPanel from '@mui/lab/TabPanel' +import Button from '@mui/material/Button' +import TabContext from '@mui/lab/TabContext' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' + +const CardNavigationCenter = () => { + // ** State + const [value, setValue] = useState('1') + + const handleChange = (event: SyntheticEvent, newValue: string) => { + setValue(newValue) + } + + return ( + + + + + + + + + + + Header One + + + Pudding tiramisu caramels. Gingerbread gummies danish chocolate bar toffee marzipan. Wafer wafer cake + powder danish oat cake. + + Button One + + + + Header Two + + + Dragée chupa chups soufflé cheesecake jelly tootsie roll cupcake marzipan. Carrot cake sweet roll gummi + bears caramels jelly beans. + + Button Two + + + + Header Three + + + Icing cake macaroon macaroon jelly chocolate bar. Chupa chups dessert dessert soufflé chocolate bar + jujubes gummi bears lollipop. + + Button Three + + + + + ) +} + +export default CardNavigationCenter diff --git a/views/cards/CardSupport.tsx b/views/cards/CardSupport.tsx new file mode 100644 index 0000000..0ba9f76 --- /dev/null +++ b/views/cards/CardSupport.tsx @@ -0,0 +1,43 @@ +// ** MUI Imports +import Card from '@mui/material/Card' +import Avatar from '@mui/material/Avatar' +import Button from '@mui/material/Button' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' + +// ** Icons Imports +import HelpCircleOutline from 'mdi-material-ui/HelpCircleOutline' + +const CardSupport = () => { + return ( + + `${theme.spacing(9.75, 5, 9.25)} !important` + }} + > + + + + + Support + + + According to us blisters are a very common thing and we come across them very often in our daily lives. It is + a very common occurrence like cold or fever depending upon your lifestyle. + + theme.spacing(1.75, 5.5) }}> + Contact Now + + + + ) +} + +export default CardSupport diff --git a/views/cards/CardTwitter.tsx b/views/cards/CardTwitter.tsx new file mode 100644 index 0000000..430afc3 --- /dev/null +++ b/views/cards/CardTwitter.tsx @@ -0,0 +1,55 @@ +// ** MUI Imports +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import Avatar from '@mui/material/Avatar' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' + +// ** Icons Imports +import Heart from 'mdi-material-ui/Heart' +import Twitter from 'mdi-material-ui/Twitter' +import ShareVariant from 'mdi-material-ui/ShareVariant' + +const CardTwitter = () => { + return ( + + `${theme.spacing(3.25, 5, 4.5)} !important` }}> + + + Twitter Card + + + Turns out semicolon-less style is easier and safer in TS because most gotcha edge cases are type invalid as + well. + + + + + + Mary Vaughn + + + + + + + 1.2k + + + + + + 80 + + + + + + + ) +} + +export default CardTwitter diff --git a/views/cards/CardUser.tsx b/views/cards/CardUser.tsx new file mode 100644 index 0000000..456d6fb --- /dev/null +++ b/views/cards/CardUser.tsx @@ -0,0 +1,63 @@ +// ** MUI Imports +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import Button from '@mui/material/Button' +import Avatar from '@mui/material/Avatar' +import CardMedia from '@mui/material/CardMedia' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' +import AvatarGroup from '@mui/material/AvatarGroup' + +const CardUser = () => { + return ( + + + `0.25rem solid ${theme.palette.common.white}` + }} + /> + + + + Robert Meyer + London, UK + + Send Request + + + + 18 mutual friends + + + + + + + + + + + + + + ) +} + +export default CardUser diff --git a/views/cards/CardVerticalRatings.tsx b/views/cards/CardVerticalRatings.tsx new file mode 100644 index 0000000..5d891ed --- /dev/null +++ b/views/cards/CardVerticalRatings.tsx @@ -0,0 +1,37 @@ +// ** MUI Imports +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import Rating from '@mui/material/Rating' +import Button from '@mui/material/Button' +import Typography from '@mui/material/Typography' +import CardHeader from '@mui/material/CardHeader' +import CardContent from '@mui/material/CardContent' +import CardActions from '@mui/material/CardActions' + +const CardVerticalRatings = () => { + return ( + + + + + + 5 Star | 98 reviews + + + If you are looking for a new way to promote your business that won’t cost you more money, maybe printing is + one of the options you won’t resist. + + + Printing is a widely use process in making printed materials that are used for advertising. It become fast, + easy and simple. If you want your promotional material to be an eye-catching. + + + + Location + Reviews + + + ) +} + +export default CardVerticalRatings diff --git a/views/cards/CardWithCollapse.tsx b/views/cards/CardWithCollapse.tsx new file mode 100644 index 0000000..4ae6704 --- /dev/null +++ b/views/cards/CardWithCollapse.tsx @@ -0,0 +1,69 @@ +// ** React Imports +import { useState } from 'react' + +// ** MUI Imports +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import Button from '@mui/material/Button' +import Divider from '@mui/material/Divider' +import Collapse from '@mui/material/Collapse' +import CardMedia from '@mui/material/CardMedia' +import Typography from '@mui/material/Typography' +import IconButton from '@mui/material/IconButton' +import CardContent from '@mui/material/CardContent' +import CardActions from '@mui/material/CardActions' + +// ** Icons Imports +import ChevronUp from 'mdi-material-ui/ChevronUp' +import ChevronDown from 'mdi-material-ui/ChevronDown' + +const CardWithCollapse = () => { + // ** State + const [collapse, setCollapse] = useState(false) + + const handleClick = () => { + setCollapse(!collapse) + } + + return ( + + + + + Popular Uses Of The Internet + + + Although cards can support multiple actions, UI controls, and an overflow menu. + + + + + Details + + {collapse ? : } + + + + + + + + I′m a thing. But, like most politicians, he promised more than he could deliver. You won′t have + time for sleeping, soldier, not with all the bed making you′ll be doing. Then we′ll go with that + data file! Hey, you add a one and two zeros to that or we walk! You′re going to do his laundry? + I′ve got to find a way to escape. + + + + + ) +} + +export default CardWithCollapse diff --git a/views/dashboard/DepositWithdraw.tsx b/views/dashboard/DepositWithdraw.tsx new file mode 100644 index 0000000..071eefe --- /dev/null +++ b/views/dashboard/DepositWithdraw.tsx @@ -0,0 +1,212 @@ +// ** MUI Imports +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import { styled } from '@mui/material/styles' +import CardHeader from '@mui/material/CardHeader' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' +import MuiDivider, { DividerProps } from '@mui/material/Divider' + +interface DataType { + logo: string + title: string + amount: string + subtitle: string + logoWidth: number + logoHeight: number +} + +const depositData = [ + { + logoWidth: 28, + logoHeight: 29, + amount: '+$4,650', + subtitle: 'Sell UI Kit', + title: 'Gumroad Account', + logo: '/images/logos/gumroad.png' + }, + { + logoWidth: 38, + logoHeight: 38, + amount: '+$92,705', + title: 'Mastercard', + subtitle: 'Wallet deposit', + logo: '/images/logos/mastercard-label.png' + }, + { + logoWidth: 20, + logoHeight: 28, + amount: '+$957', + title: 'Stripe Account', + subtitle: 'iOS Application', + logo: '/images/logos/stripe.png' + }, + { + logoWidth: 34, + logoHeight: 32, + amount: '+$6,837', + title: 'American Bank', + subtitle: 'Bank Transfer', + logo: '/images/logos/american-bank.png' + }, + { + logoWidth: 33, + logoHeight: 22, + amount: '+$446', + title: 'Bank Account', + subtitle: 'Wallet deposit', + logo: '/images/logos/citi-bank.png' + } +] + +const withdrawData = [ + { + logoWidth: 29, + logoHeight: 30, + amount: '-$145', + title: 'Google Adsense', + subtitle: 'Paypal deposit', + logo: '/images/logos/google.png' + }, + { + logoWidth: 34, + logoHeight: 34, + amount: '-$1870', + title: 'Github Enterprise', + logo: '/images/logos/github.png', + subtitle: 'Security & compliance' + }, + { + logoWidth: 30, + logoHeight: 30, + amount: '-$450', + title: 'Upgrade Slack Plan', + subtitle: 'Debit card deposit', + logo: '/images/logos/slack.png' + }, + { + logoWidth: 30, + logoHeight: 30, + amount: '-$540', + title: 'Digital Ocean', + subtitle: 'Cloud Hosting', + logo: '/images/logos/digital-ocean.png' + }, + { + logoWidth: 36, + logoHeight: 21, + amount: '-$21', + title: 'AWS Account', + logo: '/images/logos/aws.png', + subtitle: 'Choosing a Cloud Platform' + } +] + +// Styled Divider component +const Divider = styled(MuiDivider)(({ theme }) => ({ + margin: theme.spacing(5, 0), + borderRight: `1px solid ${theme.palette.divider}`, + [theme.breakpoints.down('md')]: { + borderRight: 'none', + margin: theme.spacing(0, 5), + borderBottom: `1px solid ${theme.palette.divider}` + } +})) + +const DepositWithdraw = () => { + return ( + + + View All} + titleTypographyProps={{ + variant: 'h6', + sx: { lineHeight: '1.6 !important', letterSpacing: '0.15px !important' } + }} + /> + `${theme.spacing(5.5)} !important` }}> + {depositData.map((item: DataType, index: number) => { + return ( + + + + + + + {item.title} + {item.subtitle} + + + {item.amount} + + + + ) + })} + + + + + + + View All} + titleTypographyProps={{ + variant: 'h6', + sx: { lineHeight: '1.6 !important', letterSpacing: '0.15px !important' } + }} + /> + `${theme.spacing(5.5)} !important` }}> + {withdrawData.map((item: DataType, index: number) => { + return ( + + + + + + + {item.title} + {item.subtitle} + + + {item.amount} + + + + ) + })} + + + + ) +} + +export default DepositWithdraw diff --git a/views/dashboard/SalesByCountries.tsx b/views/dashboard/SalesByCountries.tsx new file mode 100644 index 0000000..7c9b454 --- /dev/null +++ b/views/dashboard/SalesByCountries.tsx @@ -0,0 +1,169 @@ +// ** React Imports +import { ReactNode } from 'react' + +// ** MUI Imports +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import Avatar from '@mui/material/Avatar' +import Typography from '@mui/material/Typography' +import IconButton from '@mui/material/IconButton' +import CardHeader from '@mui/material/CardHeader' +import CardContent from '@mui/material/CardContent' + +// ** Icons Imports +import ChevronUp from 'mdi-material-ui/ChevronUp' +import ChevronDown from 'mdi-material-ui/ChevronDown' +import DotsVertical from 'mdi-material-ui/DotsVertical' + +// ** Types +import { ThemeColor } from '../core/layouts/types' + +interface DataType { + title: string + sales: string + trend: ReactNode + trendDir: string + subtitle: string + avatarText: string + trendNumber: string + avatarColor: ThemeColor +} + +const data: DataType[] = [ + { + sales: '894k', + trendDir: 'up', + subtitle: 'USA', + title: '$8,656k', + avatarText: 'US', + trendNumber: '25.8%', + avatarColor: 'success', + trend: + }, + { + sales: '645k', + subtitle: 'UK', + trendDir: 'down', + title: '$2,415k', + avatarText: 'UK', + trendNumber: '6.2%', + avatarColor: 'error', + trend: + }, + { + sales: '148k', + title: '$865k', + trendDir: 'up', + avatarText: 'IN', + subtitle: 'India', + trendNumber: '12.4%', + avatarColor: 'warning', + trend: + }, + { + sales: '86k', + title: '$745k', + trendDir: 'down', + avatarText: 'JA', + subtitle: 'Japan', + trendNumber: '11.9%', + avatarColor: 'secondary', + trend: + }, + { + sales: '42k', + title: '$45k', + trendDir: 'up', + avatarText: 'KO', + subtitle: 'Korea', + trendNumber: '16.2%', + avatarColor: 'error', + trend: + } +] + +const SalesByCountries = () => { + return ( + + + + + } + /> + `${theme.spacing(2)} !important` }}> + {data.map((item: DataType, index: number) => { + return ( + + + {item.avatarText} + + + + + + {item.title} + + {item.trend} + + {item.trendNumber} + + + + + {item.subtitle} + + + + + + {item.sales} + + + Sales + + + + + ) + })} + + + ) +} + +export default SalesByCountries diff --git a/views/dashboard/StatisticsCard.tsx b/views/dashboard/StatisticsCard.tsx new file mode 100644 index 0000000..f18dce5 --- /dev/null +++ b/views/dashboard/StatisticsCard.tsx @@ -0,0 +1,119 @@ +// ** React Imports +import { ReactElement } from 'react' + +// ** MUI Imports +import Box from '@mui/material/Box' +import Grid from '@mui/material/Grid' +import Card from '@mui/material/Card' +import Avatar from '@mui/material/Avatar' +import CardHeader from '@mui/material/CardHeader' +import IconButton from '@mui/material/IconButton' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' + +// ** Icons Imports +import TrendingUp from 'mdi-material-ui/TrendingUp' +import CurrencyUsd from 'mdi-material-ui/CurrencyUsd' +import DotsVertical from 'mdi-material-ui/DotsVertical' +import CellphoneLink from 'mdi-material-ui/CellphoneLink' +import AccountOutline from 'mdi-material-ui/AccountOutline' + +// ** Types +import { ThemeColor } from '../core/layouts/types' + +interface DataType { + stats: string + title: string + color: ThemeColor + icon: ReactElement +} + +const salesData: DataType[] = [ + { + stats: '245k', + title: 'Sales', + color: 'primary', + icon: + }, + { + stats: '12.5k', + title: 'Customers', + color: 'success', + icon: + }, + { + stats: '1.54k', + color: 'warning', + title: 'Products', + icon: + }, + { + stats: '$88k', + color: 'info', + title: 'Revenue', + icon: + } +] + +const renderStats = () => { + return salesData.map((item: DataType, index: number) => ( + + + + {item.icon} + + + {item.title} + {item.stats} + + + + )) +} + +const StatisticsCard = () => { + return ( + + + + + } + subheader={ + + + Total 48.5% growth + {' '} + 😎 this month + + } + titleTypographyProps={{ + sx: { + mb: 2.5, + lineHeight: '2rem !important', + letterSpacing: '0.15px !important' + } + }} + /> + `${theme.spacing(3)} !important` }}> + + {renderStats()} + + + + ) +} + +export default StatisticsCard diff --git a/views/dashboard/Table.tsx b/views/dashboard/Table.tsx new file mode 100644 index 0000000..2f89e44 --- /dev/null +++ b/views/dashboard/Table.tsx @@ -0,0 +1,164 @@ +// ** MUI Imports +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import Chip from '@mui/material/Chip' +import Table from '@mui/material/Table' +import TableRow from '@mui/material/TableRow' +import TableHead from '@mui/material/TableHead' +import TableBody from '@mui/material/TableBody' +import TableCell from '@mui/material/TableCell' +import Typography from '@mui/material/Typography' +import TableContainer from '@mui/material/TableContainer' + +// ** Types Imports +import { ThemeColor } from '../core/layouts/types' + +interface RowType { + age: number + name: string + date: string + email: string + salary: string + status: string + designation: string +} + +interface StatusObj { + [key: string]: { + color: ThemeColor + } +} + +const rows: RowType[] = [ + { + age: 27, + status: 'current', + date: '09/27/2018', + name: 'Sally Quinn', + salary: '$19586.23', + email: 'eebsworth2m@sbwire.com', + designation: 'Human Resources Assistant' + }, + { + age: 61, + date: '09/23/2016', + salary: '$23896.35', + status: 'professional', + name: 'Margaret Bowers', + email: 'kocrevy0@thetimes.co.uk', + designation: 'Nuclear Power Engineer' + }, + { + age: 59, + date: '10/15/2017', + name: 'Minnie Roy', + status: 'rejected', + salary: '$18991.67', + email: 'ediehn6@163.com', + designation: 'Environmental Specialist' + }, + { + age: 30, + date: '06/12/2018', + status: 'resigned', + salary: '$19252.12', + name: 'Ralph Leonard', + email: 'dfalloona@ifeng.com', + designation: 'Sales Representative' + }, + { + age: 66, + status: 'applied', + date: '03/24/2018', + salary: '$13076.28', + name: 'Annie Martin', + designation: 'Operator', + email: 'sganderton2@tuttocitta.it' + }, + { + age: 33, + date: '08/25/2017', + salary: '$10909.52', + name: 'Adeline Day', + status: 'professional', + email: 'hnisius4@gnu.org', + designation: 'Senior Cost Accountant' + }, + { + age: 61, + status: 'current', + date: '06/01/2017', + salary: '$17803.80', + name: 'Lora Jackson', + designation: 'Geologist', + email: 'ghoneywood5@narod.ru' + }, + { + age: 22, + date: '12/03/2017', + salary: '$12336.17', + name: 'Rodney Sharp', + status: 'professional', + designation: 'Cost Accountant', + email: 'dcrossman3@google.co.jp' + } +] + +const statusObj: StatusObj = { + applied: { color: 'info' }, + rejected: { color: 'error' }, + current: { color: 'primary' }, + resigned: { color: 'warning' }, + professional: { color: 'success' } +} + +const DashboardTable = () => { + return ( + + + + + + Name + Email + Date + Salary + Age + Status + + + + {rows.map((row: RowType) => ( + + `${theme.spacing(0.5)} !important` }}> + + {row.name} + {row.designation} + + + {row.email} + {row.date} + {row.salary} + {row.age} + + + + + ))} + + + + + ) +} + +export default DashboardTable diff --git a/views/dashboard/TotalEarning.tsx b/views/dashboard/TotalEarning.tsx new file mode 100644 index 0000000..0902f5d --- /dev/null +++ b/views/dashboard/TotalEarning.tsx @@ -0,0 +1,139 @@ +// ** MUI Imports +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import Avatar from '@mui/material/Avatar' +import Typography from '@mui/material/Typography' +import IconButton from '@mui/material/IconButton' +import CardHeader from '@mui/material/CardHeader' +import CardContent from '@mui/material/CardContent' +import LinearProgress from '@mui/material/LinearProgress' + +// ** Icons Imports +import MenuUp from 'mdi-material-ui/MenuUp' +import DotsVertical from 'mdi-material-ui/DotsVertical' + +// ** Types +import { ThemeColor } from '../../core/layouts/types' + +interface DataType { + title: string + imgSrc: string + amount: string + subtitle: string + progress: number + color: ThemeColor + imgHeight: number +} + +const data: DataType[] = [ + { + progress: 75, + imgHeight: 20, + title: 'Zipcar', + color: 'primary', + amount: '$24,895.65', + subtitle: 'Vuejs, React & HTML', + imgSrc: '/images/cards/logo-zipcar.png' + }, + { + progress: 50, + color: 'info', + imgHeight: 27, + title: 'Bitbank', + amount: '$8,650.20', + subtitle: 'Sketch, Figma & XD', + imgSrc: '/images/cards/logo-bitbank.png' + }, + { + progress: 20, + imgHeight: 20, + title: 'Aviato', + color: 'secondary', + amount: '$1,245.80', + subtitle: 'HTML & Angular', + imgSrc: '/images/cards/logo-aviato.png' + } +] + +const TotalEarning = () => { + return ( + + + + + } + /> + `${theme.spacing(2.25)} !important` }}> + + + $24,895 + + + + + 10% + + + + + + Compared to $84,325 last year + + + {data.map((item: DataType, index: number) => { + return ( + + `rgba(${theme.palette.customColors.main}, 0.04)` + }} + > + + + + + + {item.title} + + {item.subtitle} + + + + + {item.amount} + + + + + + ) + })} + + + ) +} + +export default TotalEarning diff --git a/views/dashboard/Trophy.tsx b/views/dashboard/Trophy.tsx new file mode 100644 index 0000000..c2b2eb8 --- /dev/null +++ b/views/dashboard/Trophy.tsx @@ -0,0 +1,50 @@ +// ** MUI Imports +import Card from '@mui/material/Card' +import Button from '@mui/material/Button' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' +import { styled, useTheme } from '@mui/material/styles' + +// Styled component for the triangle shaped background image +const TriangleImg = styled('img')({ + right: 0, + bottom: 0, + height: 170, + position: 'absolute' +}) + +// Styled component for the trophy image +const TrophyImg = styled('img')({ + right: 36, + bottom: 20, + height: 98, + position: 'absolute' +}) + +const Trophy = () => { + // ** Hook + const theme = useTheme() + + const imageSrc = theme.palette.mode === 'light' ? 'triangle-light.png' : 'triangle-dark.png' + + return ( + + + Congratulations John! 🥳 + + Best seller of the month + + + $42.8k + + + View Sales + + + + + + ) +} + +export default Trophy diff --git a/views/dashboard/WeeklyOverview.tsx b/views/dashboard/WeeklyOverview.tsx new file mode 100644 index 0000000..09e814c --- /dev/null +++ b/views/dashboard/WeeklyOverview.tsx @@ -0,0 +1,115 @@ +// ** MUI Imports +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import Button from '@mui/material/Button' +import { useTheme } from '@mui/material/styles' +import CardHeader from '@mui/material/CardHeader' +import IconButton from '@mui/material/IconButton' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' + +// ** Icons Imports +import DotsVertical from 'mdi-material-ui/DotsVertical' + +// ** Third Party Imports +import { ApexOptions } from 'apexcharts' + +// ** Custom Components Imports +import ReactApexcharts from '../../core/components/react-apexcharts' + +const WeeklyOverview = () => { + // ** Hook + const theme = useTheme() + + const options: ApexOptions = { + chart: { + parentHeightOffset: 0, + toolbar: { show: false } + }, + plotOptions: { + bar: { + borderRadius: 9, + distributed: true, + columnWidth: '40%', + endingShape: 'rounded', + startingShape: 'rounded' + } + }, + stroke: { + width: 2, + colors: [theme.palette.background.paper] + }, + legend: { show: false }, + grid: { + strokeDashArray: 7, + padding: { + top: -1, + right: 0, + left: -12, + bottom: 5 + } + }, + dataLabels: { enabled: false }, + colors: [ + theme.palette.background.default, + theme.palette.background.default, + theme.palette.background.default, + theme.palette.primary.main, + theme.palette.background.default, + theme.palette.background.default + ], + states: { + hover: { + filter: { type: 'none' } + }, + active: { + filter: { type: 'none' } + } + }, + xaxis: { + categories: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + tickPlacement: 'on', + labels: { show: false }, + axisTicks: { show: false }, + axisBorder: { show: false } + }, + yaxis: { + show: true, + tickAmount: 4, + labels: { + offsetX: -17, + formatter: value => `${value > 999 ? `${(value / 1000).toFixed(0)}` : value}k` + } + } + } + + return ( + + + + + } + /> + + + + + 45% + + Your sales performance is 45% 😎 better compared to last month + + + Details + + + + ) +} + +export default WeeklyOverview diff --git a/views/form-layouts/FormLayoutsAlignment.tsx b/views/form-layouts/FormLayoutsAlignment.tsx new file mode 100644 index 0000000..318fe29 --- /dev/null +++ b/views/form-layouts/FormLayoutsAlignment.tsx @@ -0,0 +1,111 @@ +// ** React Imports +import { ChangeEvent, MouseEvent, useState } from 'react' + +// ** MUI Imports +import Card from '@mui/material/Card' +import Grid from '@mui/material/Grid' +import Button from '@mui/material/Button' +import Checkbox from '@mui/material/Checkbox' +import { styled } from '@mui/material/styles' +import TextField from '@mui/material/TextField' +import CardHeader from '@mui/material/CardHeader' +import Typography from '@mui/material/Typography' +import InputLabel from '@mui/material/InputLabel' +import IconButton from '@mui/material/IconButton' +import CardContent from '@mui/material/CardContent' +import FormControl from '@mui/material/FormControl' +import OutlinedInput from '@mui/material/OutlinedInput' +import InputAdornment from '@mui/material/InputAdornment' +import FormControlLabel from '@mui/material/FormControlLabel' + +// ** Icons Imports +import EyeOutline from 'mdi-material-ui/EyeOutline' +import EyeOffOutline from 'mdi-material-ui/EyeOffOutline' + +interface State { + password: string + showPassword: boolean +} + +// Styled component for the form +const Form = styled('form')(({ theme }) => ({ + maxWidth: 400, + padding: theme.spacing(12), + borderRadius: theme.shape.borderRadius, + border: `1px solid ${theme.palette.divider}` +})) + +const FormLayoutsAlignment = () => { + // ** State + const [values, setValues] = useState({ + password: '', + showPassword: false + }) + + // Handle Password + const handleChange = (prop: keyof State) => (event: ChangeEvent) => { + setValues({ ...values, [prop]: event.target.value }) + } + const handleClickShowPassword = () => { + setValues({ ...values, showPassword: !values.showPassword }) + } + const handleMouseDownPassword = (event: MouseEvent) => { + event.preventDefault() + } + + return ( + + + + e.preventDefault()}> + + + Sign In + + + + + + + Password + + + {values.showPassword ? : } + + + } + /> + + + + } + sx={{ '& .MuiButtonBase-root': { paddingTop: 0, paddingBottom: 0 } }} + /> + + + + Login + + + + + + + ) +} + +export default FormLayoutsAlignment diff --git a/views/form-layouts/FormLayoutsBasic.tsx b/views/form-layouts/FormLayoutsBasic.tsx new file mode 100644 index 0000000..aa2daba --- /dev/null +++ b/views/form-layouts/FormLayoutsBasic.tsx @@ -0,0 +1,162 @@ +// ** React Imports +import { ChangeEvent, MouseEvent, useState, SyntheticEvent } from 'react' + +// ** MUI Imports +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import Grid from '@mui/material/Grid' +import Link from '@mui/material/Link' +import Button from '@mui/material/Button' +import TextField from '@mui/material/TextField' +import CardHeader from '@mui/material/CardHeader' +import InputLabel from '@mui/material/InputLabel' +import IconButton from '@mui/material/IconButton' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' +import FormControl from '@mui/material/FormControl' +import OutlinedInput from '@mui/material/OutlinedInput' +import InputAdornment from '@mui/material/InputAdornment' +import FormHelperText from '@mui/material/FormHelperText' + +// ** Icons Imports +import EyeOutline from 'mdi-material-ui/EyeOutline' +import EyeOffOutline from 'mdi-material-ui/EyeOffOutline' + +interface State { + password: string + showPassword: boolean +} + +const FormLayoutsBasic = () => { + // ** States + const [values, setValues] = useState({ + password: '', + showPassword: false + }) + const [confirmPassValues, setConfirmPassValues] = useState({ + password: '', + showPassword: false + }) + + const handleChange = (prop: keyof State) => (event: ChangeEvent) => { + setValues({ ...values, [prop]: event.target.value }) + } + + const handleConfirmPassChange = (prop: keyof State) => (event: ChangeEvent) => { + setConfirmPassValues({ ...confirmPassValues, [prop]: event.target.value }) + } + const handleClickShowPassword = () => { + setValues({ ...values, showPassword: !values.showPassword }) + } + + const handleClickConfirmPassShow = () => { + setConfirmPassValues({ ...confirmPassValues, showPassword: !confirmPassValues.showPassword }) + } + + const handleMouseDownPassword = (event: MouseEvent) => { + event.preventDefault() + } + + return ( + + + + e.preventDefault()}> + + + + + + + + + + Password + + + {values.showPassword ? : } + + + } + /> + + Use 8 or more characters with a mix of letters, numbers & symbols + + + + + + Confirm Password + + + {confirmPassValues.showPassword ? : } + + + } + /> + + Make sure to type the same password as above + + + + + + + Get Started! + + + Already have an account? + e.preventDefault()}> + Log in + + + + + + + + + ) +} + +export default FormLayoutsBasic diff --git a/views/form-layouts/FormLayoutsIcons.tsx b/views/form-layouts/FormLayoutsIcons.tsx new file mode 100644 index 0000000..4d6bfc0 --- /dev/null +++ b/views/form-layouts/FormLayoutsIcons.tsx @@ -0,0 +1,97 @@ +// ** MUI Imports +import Card from '@mui/material/Card' +import Grid from '@mui/material/Grid' +import Button from '@mui/material/Button' +import TextField from '@mui/material/TextField' +import CardHeader from '@mui/material/CardHeader' +import CardContent from '@mui/material/CardContent' +import InputAdornment from '@mui/material/InputAdornment' + +// ** Icons Imports +import Phone from 'mdi-material-ui/Phone' +import EmailOutline from 'mdi-material-ui/EmailOutline' +import AccountOutline from 'mdi-material-ui/AccountOutline' +import MessageOutline from 'mdi-material-ui/MessageOutline' + +const FormLayoutsIcons = () => { + return ( + + + + e.preventDefault()}> + + + + + + ) + }} + /> + + + + + + ) + }} + /> + + + + + + ) + }} + /> + + + + + + ) + }} + /> + + + + Submit + + + + + + + ) +} + +export default FormLayoutsIcons diff --git a/views/form-layouts/FormLayoutsSeparator.tsx b/views/form-layouts/FormLayoutsSeparator.tsx new file mode 100644 index 0000000..11864be --- /dev/null +++ b/views/form-layouts/FormLayoutsSeparator.tsx @@ -0,0 +1,225 @@ +// ** React Imports +import { ChangeEvent, forwardRef, MouseEvent, useState } from 'react' + +// ** MUI Imports +import Card from '@mui/material/Card' +import Grid from '@mui/material/Grid' +import Button from '@mui/material/Button' +import Divider from '@mui/material/Divider' +import MenuItem from '@mui/material/MenuItem' +import TextField from '@mui/material/TextField' +import CardHeader from '@mui/material/CardHeader' +import InputLabel from '@mui/material/InputLabel' +import IconButton from '@mui/material/IconButton' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' +import CardActions from '@mui/material/CardActions' +import FormControl from '@mui/material/FormControl' +import OutlinedInput from '@mui/material/OutlinedInput' +import InputAdornment from '@mui/material/InputAdornment' +import Select, { SelectChangeEvent } from '@mui/material/Select' + +// ** Third Party Imports +import DatePicker from 'react-datepicker' + +// ** Icons Imports +import EyeOutline from 'mdi-material-ui/EyeOutline' +import EyeOffOutline from 'mdi-material-ui/EyeOffOutline' + +interface State { + password: string + password2: string + showPassword: boolean + showPassword2: boolean +} + +const CustomInput = forwardRef((props, ref) => { + return +}) + +const FormLayoutsSeparator = () => { + // ** States + const [language, setLanguage] = useState([]) + const [date, setDate] = useState(null) + const [values, setValues] = useState({ + password: '', + password2: '', + showPassword: false, + showPassword2: false + }) + + // Handle Password + const handlePasswordChange = (prop: keyof State) => (event: ChangeEvent) => { + setValues({ ...values, [prop]: event.target.value }) + } + const handleClickShowPassword = () => { + setValues({ ...values, showPassword: !values.showPassword }) + } + const handleMouseDownPassword = (event: MouseEvent) => { + event.preventDefault() + } + + // Handle Confirm Password + const handleConfirmChange = (prop: keyof State) => (event: ChangeEvent) => { + setValues({ ...values, [prop]: event.target.value }) + } + const handleClickShowConfirmPassword = () => { + setValues({ ...values, showPassword2: !values.showPassword2 }) + } + const handleMouseDownConfirmPassword = (event: MouseEvent) => { + event.preventDefault() + } + + // Handle Select + const handleSelectChange = (event: SelectChangeEvent) => { + setLanguage(event.target.value as string[]) + } + + return ( + + + + e.preventDefault()}> + + + + + 1. Account Details + + + + + + + + + + + Password + + + {values.showPassword ? : } + + + } + /> + + + + + Confirm Password + + + {values.showPassword2 ? : } + + + } + /> + + + + + + + + 2. Personal Info + + + + + + + + + + + Country + + UK + USA + Australia + Germany + + + + + + Language + } + > + English + French + Spanish + Portuguese + Italian + German + Arabic + + + + + } + id='form-layouts-separator-date' + onChange={(date: Date) => setDate(date)} + /> + + + + + + + + + + Submit + + + Cancel + + + + + ) +} + +export default FormLayoutsSeparator diff --git a/views/pages/auth/FooterIllustration.tsx b/views/pages/auth/FooterIllustration.tsx new file mode 100644 index 0000000..c8fdb69 --- /dev/null +++ b/views/pages/auth/FooterIllustration.tsx @@ -0,0 +1,56 @@ +// ** React Imports +import { Fragment, ReactNode } from 'react' + +// ** MUI Components +import useMediaQuery from '@mui/material/useMediaQuery' +import { styled, useTheme } from '@mui/material/styles' + +interface FooterIllustrationsProp { + image1?: ReactNode + image2?: ReactNode +} + +// Styled Components +const MaskImg = styled('img')(() => ({ + bottom: 0, + zIndex: -1, + width: '100%', + position: 'absolute' +})) + +const Tree1Img = styled('img')(() => ({ + left: 0, + bottom: 0, + position: 'absolute' +})) + +const Tree2Img = styled('img')(() => ({ + right: 0, + bottom: 0, + position: 'absolute' +})) + +const FooterIllustrationsV1 = (props: FooterIllustrationsProp) => { + // ** Props + const { image1, image2 } = props + + // ** Hook + const theme = useTheme() + + // ** Vars + const hidden = useMediaQuery(theme.breakpoints.down('md')) + + if (!hidden) { + return ( + + {image1 || } + + {image2 || } + + ) + } else { + return null + } +} + +export default FooterIllustrationsV1 diff --git a/views/pages/misc/FooterIllustrations.tsx b/views/pages/misc/FooterIllustrations.tsx new file mode 100644 index 0000000..a656b71 --- /dev/null +++ b/views/pages/misc/FooterIllustrations.tsx @@ -0,0 +1,52 @@ +// ** React Imports +import { Fragment, ReactNode } from 'react' + +// ** MUI Components +import useMediaQuery from '@mui/material/useMediaQuery' +import { styled, useTheme } from '@mui/material/styles' + +interface FooterIllustrationsProp { + image?: ReactNode +} + +// Styled Components +const MaskImg = styled('img')(() => ({ + bottom: 0, + zIndex: -1, + width: '100%', + position: 'absolute' +})) + +const TreeImg = styled('img')(({ theme }) => ({ + left: '2.25rem', + bottom: '4.25rem', + position: 'absolute', + [theme.breakpoints.down('lg')]: { + left: 0, + bottom: 0 + } +})) + +const FooterIllustrations = (props: FooterIllustrationsProp) => { + // ** Props + const { image } = props + + // ** Hook + const theme = useTheme() + + // ** Vars + const hidden = useMediaQuery(theme.breakpoints.down('md')) + + if (!hidden) { + return ( + + {image || } + + + ) + } else { + return null + } +} + +export default FooterIllustrations diff --git a/views/tables/TableBasic.tsx b/views/tables/TableBasic.tsx new file mode 100644 index 0000000..5105ef2 --- /dev/null +++ b/views/tables/TableBasic.tsx @@ -0,0 +1,60 @@ +// ** MUI Imports +import Paper from '@mui/material/Paper' +import Table from '@mui/material/Table' +import TableRow from '@mui/material/TableRow' +import TableHead from '@mui/material/TableHead' +import TableBody from '@mui/material/TableBody' +import TableCell from '@mui/material/TableCell' +import TableContainer from '@mui/material/TableContainer' + +const createData = (name: string, calories: number, fat: number, carbs: number, protein: number) => { + return { name, calories, fat, carbs, protein } +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9) +] + +const TableBasic = () => { + return ( + + + + + Dessert (100g serving) + Calories + Fat (g) + Carbs (g) + Protein (g) + + + + {rows.map(row => ( + + + {row.name} + + {row.calories} + {row.fat} + {row.carbs} + {row.protein} + + ))} + + + + ) +} + +export default TableBasic diff --git a/views/tables/TableCollapsible.tsx b/views/tables/TableCollapsible.tsx new file mode 100644 index 0000000..98489ff --- /dev/null +++ b/views/tables/TableCollapsible.tsx @@ -0,0 +1,136 @@ +// ** React Imports +import { useState, Fragment } from 'react' + +// ** MUI Imports +import Box from '@mui/material/Box' +import Paper from '@mui/material/Paper' +import Table from '@mui/material/Table' +import Collapse from '@mui/material/Collapse' +import TableRow from '@mui/material/TableRow' +import TableHead from '@mui/material/TableHead' +import TableBody from '@mui/material/TableBody' +import TableCell from '@mui/material/TableCell' +import Typography from '@mui/material/Typography' +import IconButton from '@mui/material/IconButton' +import TableContainer from '@mui/material/TableContainer' + +// ** Icons Imports +import ChevronUp from 'mdi-material-ui/ChevronUp' +import ChevronDown from 'mdi-material-ui/ChevronDown' + +const createData = (name: string, calories: number, fat: number, carbs: number, protein: number, price: number) => { + return { + name, + calories, + fat, + carbs, + protein, + price, + history: [ + { + date: '2020-01-05', + customerId: '11091700', + amount: 3 + }, + { + date: '2020-01-02', + customerId: 'Anonymous', + amount: 1 + } + ] + } +} + +const Row = (props: { row: ReturnType }) => { + // ** Props + const { row } = props + + // ** State + const [open, setOpen] = useState(false) + + return ( + + *': { borderBottom: 'unset' } }}> + + setOpen(!open)}> + {open ? : } + + + + {row.name} + + {row.calories} + {row.fat} + {row.carbs} + {row.protein} + + + + + + + History + + + + + Date + Customer + Amount + Total price ($) + + + + {row.history.map(historyRow => ( + + + {historyRow.date} + + {historyRow.customerId} + {historyRow.amount} + {Math.round(historyRow.amount * row.price * 100) / 100} + + ))} + + + + + + + + ) +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0, 3.99), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3, 4.99), + createData('Eclair', 262, 16.0, 24, 6.0, 3.79), + createData('Cupcake', 305, 3.7, 67, 4.3, 2.5), + createData('Gingerbread', 356, 16.0, 49, 3.9, 1.5) +] + +const TableCollapsible = () => { + return ( + + + + + + Dessert (100g serving) + Calories + Fat (g) + Carbs (g) + Protein (g) + + + + {rows.map(row => ( + + ))} + + + + ) +} + +export default TableCollapsible diff --git a/views/tables/TableCustomized.tsx b/views/tables/TableCustomized.tsx new file mode 100644 index 0000000..87f78d6 --- /dev/null +++ b/views/tables/TableCustomized.tsx @@ -0,0 +1,75 @@ +// ** MUI Imports +import Paper from '@mui/material/Paper' +import Table from '@mui/material/Table' +import { styled } from '@mui/material/styles' +import TableHead from '@mui/material/TableHead' +import TableBody from '@mui/material/TableBody' +import TableContainer from '@mui/material/TableContainer' +import TableRow, { TableRowProps } from '@mui/material/TableRow' +import TableCell, { TableCellProps, tableCellClasses } from '@mui/material/TableCell' + +const StyledTableCell = styled(TableCell)(({ theme }) => ({ + [`&.${tableCellClasses.head}`]: { + color: theme.palette.common.white, + backgroundColor: theme.palette.common.black + }, + [`&.${tableCellClasses.body}`]: { + fontSize: 14 + } +})) + +const StyledTableRow = styled(TableRow)(({ theme }) => ({ + '&:nth-of-type(odd)': { + backgroundColor: theme.palette.action.hover + }, + + // hide last border + '&:last-of-type td, &:last-of-type th': { + border: 0 + } +})) + +const createData = (name: string, calories: number, fat: number, carbs: number, protein: number) => { + return { name, calories, fat, carbs, protein } +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9) +] + +const TableCustomized = () => { + return ( + + + + + Dessert (100g serving) + Calories + Fat (g) + Carbs (g) + Protein (g) + + + + {rows.map(row => ( + + + {row.name} + + {row.calories} + {row.fat} + {row.carbs} + {row.protein} + + ))} + + + + ) +} + +export default TableCustomized diff --git a/views/tables/TableDense.tsx b/views/tables/TableDense.tsx new file mode 100644 index 0000000..2730ebf --- /dev/null +++ b/views/tables/TableDense.tsx @@ -0,0 +1,53 @@ +// ** MUI Imports +import Paper from '@mui/material/Paper' +import Table from '@mui/material/Table' +import TableRow from '@mui/material/TableRow' +import TableHead from '@mui/material/TableHead' +import TableBody from '@mui/material/TableBody' +import TableCell from '@mui/material/TableCell' +import TableContainer from '@mui/material/TableContainer' + +const createData = (name: string, calories: number, fat: number, carbs: number, protein: number) => { + return { name, calories, fat, carbs, protein } +} + +const rows = [ + createData('Frozen yoghurt', 159, 6.0, 24, 4.0), + createData('Ice cream sandwich', 237, 9.0, 37, 4.3), + createData('Eclair', 262, 16.0, 24, 6.0), + createData('Cupcake', 305, 3.7, 67, 4.3), + createData('Gingerbread', 356, 16.0, 49, 3.9) +] + +const TableDense = () => { + return ( + + + + + Dessert (100g serving) + Calories + Fat (g) + Carbs (g) + Protein (g) + + + + {rows.map(row => ( + + + {row.name} + + {row.calories} + {row.fat} + {row.carbs} + {row.protein} + + ))} + + + + ) +} + +export default TableDense diff --git a/views/tables/TableSpanning.tsx b/views/tables/TableSpanning.tsx new file mode 100644 index 0000000..6a8080b --- /dev/null +++ b/views/tables/TableSpanning.tsx @@ -0,0 +1,94 @@ +// ** MUI Imports +import Paper from '@mui/material/Paper' +import Table from '@mui/material/Table' +import TableRow from '@mui/material/TableRow' +import TableHead from '@mui/material/TableHead' +import TableBody from '@mui/material/TableBody' +import TableCell from '@mui/material/TableCell' +import TableContainer from '@mui/material/TableContainer' + +interface Row { + desc: string + qty: number + unit: number + price: number +} + +const TAX_RATE = 0.07 + +const ccyFormat = (num: number) => { + return `${num.toFixed(2)}` +} + +const priceRow = (qty: number, unit: number) => { + return qty * unit +} + +const createRow = (desc: string, qty: number, unit: number) => { + const price = priceRow(qty, unit) + + return { desc, qty, unit, price } +} + +const subtotal = (items: readonly Row[]) => { + return items.map(({ price }) => price).reduce((sum, i) => sum + i, 0) +} + +const rows = [ + createRow('Paperclips (Box)', 100, 1.15), + createRow('Paper (Case)', 10, 45.99), + createRow('Waste Basket', 2, 17.99) +] + +const invoiceSubtotal = subtotal(rows) +const invoiceTaxes = TAX_RATE * invoiceSubtotal +const invoiceTotal = invoiceTaxes + invoiceSubtotal + +const TableSpanning = () => { + return ( + + + + + + Details + + Price + + + Desc + Qty. + Unit + Sum + + + + {rows.map(row => ( + + {row.desc} + {row.qty} + {row.unit} + {ccyFormat(row.price)} + + ))} + + + Subtotal + {ccyFormat(invoiceSubtotal)} + + + Tax + {`${(TAX_RATE * 100).toFixed(0)} %`} + {ccyFormat(invoiceTaxes)} + + + Total + {ccyFormat(invoiceTotal)} + + + + + ) +} + +export default TableSpanning diff --git a/views/tables/TableStickyHeader.tsx b/views/tables/TableStickyHeader.tsx new file mode 100644 index 0000000..1cda4aa --- /dev/null +++ b/views/tables/TableStickyHeader.tsx @@ -0,0 +1,139 @@ +// ** React Imports +import { useState, ChangeEvent } from 'react' + +// ** MUI Imports +import Paper from '@mui/material/Paper' +import Table from '@mui/material/Table' +import TableRow from '@mui/material/TableRow' +import TableHead from '@mui/material/TableHead' +import TableBody from '@mui/material/TableBody' +import TableCell from '@mui/material/TableCell' +import TableContainer from '@mui/material/TableContainer' +import TablePagination from '@mui/material/TablePagination' + +interface Column { + id: 'name' | 'code' | 'population' | 'size' | 'density' + label: string + minWidth?: number + align?: 'right' + format?: (value: number) => string +} + +const columns: readonly Column[] = [ + { id: 'name', label: 'Name', minWidth: 170 }, + { id: 'code', label: 'ISO\u00a0Code', minWidth: 100 }, + { + id: 'population', + label: 'Population', + minWidth: 170, + align: 'right', + format: (value: number) => value.toLocaleString('en-US') + }, + { + id: 'size', + label: 'Size\u00a0(km\u00b2)', + minWidth: 170, + align: 'right', + format: (value: number) => value.toLocaleString('en-US') + }, + { + id: 'density', + label: 'Density', + minWidth: 170, + align: 'right', + format: (value: number) => value.toFixed(2) + } +] + +interface Data { + name: string + code: string + size: number + density: number + population: number +} + +function createData(name: string, code: string, population: number, size: number): Data { + const density = population / size + + return { name, code, population, size, density } +} + +const rows = [ + createData('India', 'IN', 1324171354, 3287263), + createData('China', 'CN', 1403500365, 9596961), + createData('Italy', 'IT', 60483973, 301340), + createData('United States', 'US', 327167434, 9833520), + createData('Canada', 'CA', 37602103, 9984670), + createData('Australia', 'AU', 25475400, 7692024), + createData('Germany', 'DE', 83019200, 357578), + createData('Ireland', 'IE', 4857000, 70273), + createData('Mexico', 'MX', 126577691, 1972550), + createData('Japan', 'JP', 126317000, 377973), + createData('France', 'FR', 67022000, 640679), + createData('United Kingdom', 'GB', 67545757, 242495), + createData('Russia', 'RU', 146793744, 17098246), + createData('Nigeria', 'NG', 200962417, 923768), + createData('Brazil', 'BR', 210147125, 8515767) +] + +const TableStickyHeader = () => { + // ** States + const [page, setPage] = useState(0) + const [rowsPerPage, setRowsPerPage] = useState(10) + + const handleChangePage = (event: unknown, newPage: number) => { + setPage(newPage) + } + + const handleChangeRowsPerPage = (event: ChangeEvent) => { + setRowsPerPage(+event.target.value) + setPage(0) + } + + return ( + + + + + + {columns.map(column => ( + + {column.label} + + ))} + + + + {rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map(row => { + return ( + + {columns.map(column => { + const value = row[column.id] + + return ( + + {column.format && typeof value === 'number' ? column.format(value) : value} + + ) + })} + + ) + })} + + + + + + ) +} + +export default TableStickyHeader diff --git a/views/typography/TypographyHeadings.tsx b/views/typography/TypographyHeadings.tsx new file mode 100644 index 0000000..6856a7b --- /dev/null +++ b/views/typography/TypographyHeadings.tsx @@ -0,0 +1,86 @@ +// ** MUI Imports +import Card from '@mui/material/Card' +import { styled } from '@mui/material/styles' +import CardHeader from '@mui/material/CardHeader' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' +import Grid, { GridProps } from '@mui/material/Grid' + +const DemoGrid = styled(Grid)(({ theme }) => ({ + [theme.breakpoints.down('sm')]: { + paddingTop: `${theme.spacing(1)} !important` + } +})) + +const TypographyHeadings = () => { + return ( + + + + + + H1 + + + + Heading 1 + + font-size: 96px / line-height: 112px / font-weight: 500 + + + + H2 + + + + Heading 2 + + font-size: 60px / line-height: 72px / font-weight: 500 + + + + H3 + + + + Heading 3 + + font-size: 48px / line-height: 56px / font-weight: 500 + + + + H4 + + + + Heading 4 + + font-size: 32px / line-height: 40px / font-weight: 500 + + + + H5 + + + + Heading 5 + + font-size: 24px / line-height: 32px / font-weight: 500 + + + + H6 + + + + Heading 6 + + font-size: 20px / line-height: 32px / font-weight: 500 + + + + + ) +} + +export default TypographyHeadings diff --git a/views/typography/TypographyTexts.tsx b/views/typography/TypographyTexts.tsx new file mode 100644 index 0000000..cf99ec2 --- /dev/null +++ b/views/typography/TypographyTexts.tsx @@ -0,0 +1,96 @@ +// ** MUI Imports +import Card from '@mui/material/Card' +import { styled } from '@mui/material/styles' +import CardHeader from '@mui/material/CardHeader' +import Typography from '@mui/material/Typography' +import CardContent from '@mui/material/CardContent' +import Grid, { GridProps } from '@mui/material/Grid' + +const DemoGrid = styled(Grid)(({ theme }) => ({ + [theme.breakpoints.down('sm')]: { + paddingTop: `${theme.spacing(1)} !important` + } +})) + +const TypographyTexts = () => { + return ( + + + + + + subtitle1 + + + + Cupcake ipsum dolor sit amet chocolate bar pastry sesame snaps. + + font-size: 16px / line-height: 28px / font-weight: 400 + + + + subtitle2 + + + + Cupcake ipsum dolor sit amet chocolate bar pastry sesame snaps. + + font-size: 14px / line-height: 21px / font-weight: 500 + + + + body1 + + + + Cupcake ipsum dolor sit amet chocolate bar pastry sesame snaps. + + font-size: 16px / line-height: 24px / font-weight: 400 + + + + body2 + + + + Cupcake ipsum dolor sit amet chocolate bar pastry sesame snaps. + + font-size: 14px / line-height: 21px / font-weight: 400 + + + + button + + + Button Text + + font-size: 14px / line-height: 17px / font-weight: 500 / text-transform: uppercase + + + + + caption + + + Cupcake ipsum dolor sit amet chocolate bar pastry sesame snaps. + + font-size: 12px / line-height: 15px / font-weight: 400 + + + + + overline + + + Cupcake ipsum dolor sit amet chocolate bar pastry sesame snaps. + + font-size: 12px / line-height: 15px / font-weight: 400 / text-transform: uppercase + + + + + + ) +} + +export default TypographyTexts