feat:landing page

This commit is contained in:
Damien Ostler 2024-02-15 21:49:12 -05:00
parent c8b1dfb3ba
commit 937faf1847
20 changed files with 1344 additions and 230 deletions

252
components/AppAppBar.tsx Normal file
View File

@ -0,0 +1,252 @@
import * as React from 'react';
import { PaletteMode } from '@mui/material';
import Box from '@mui/material/Box';
import AppBar from '@mui/material/AppBar';
import Toolbar from '@mui/material/Toolbar';
import Button from '@mui/material/Button';
import Container from '@mui/material/Container';
import Divider from '@mui/material/Divider';
import Typography from '@mui/material/Typography';
import MenuItem from '@mui/material/MenuItem';
import Drawer from '@mui/material/Drawer';
import MenuIcon from '@mui/icons-material/Menu';
import ToggleColorMode from './ToggleColorMode';
import { ArrowLeftOutlined, ArrowRightRounded, OpenInNew } from '@mui/icons-material';
const logoStyle = {
width: '140px',
height: 'auto',
cursor: 'pointer',
};
interface AppAppBarProps {
user: any;
}
function AppAppBar({ user }: AppAppBarProps) {
const [open, setOpen] = React.useState(false);
const toggleDrawer = (newOpen: boolean) => () => {
setOpen(newOpen);
};
const scrollToSection = (sectionId: string) => {
const sectionElement = document.getElementById(sectionId);
const offset = 128;
if (sectionElement) {
const targetScroll = sectionElement.offsetTop - offset;
sectionElement.scrollIntoView({ behavior: 'smooth' });
window.scrollTo({
top: targetScroll,
behavior: 'smooth',
});
setOpen(false);
}
};
return (
<div>
<AppBar
position="fixed"
sx={{
boxShadow: 0,
bgcolor: 'transparent',
backgroundImage: 'none',
mt: 2,
}}
>
<Container maxWidth="lg">
<Toolbar
variant="regular"
sx={(theme) => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
flexShrink: 0,
borderRadius: '999px',
bgcolor:
theme.palette.mode === 'light'
? 'rgba(255, 255, 255, 0.4)'
: 'rgba(0, 0, 0, 0.4)',
backdropFilter: 'blur(24px)',
maxHeight: 40,
border: '1px solid',
borderColor: 'divider',
boxShadow:
theme.palette.mode === 'light'
? `0 0 1px rgba(85, 166, 246, 0.1), 1px 1.5px 2px -1px rgba(85, 166, 246, 0.15), 4px 4px 12px -2.5px rgba(85, 166, 246, 0.15)`
: '0 0 1px rgba(2, 31, 59, 0.7), 1px 1.5px 2px -1px rgba(2, 31, 59, 0.65), 4px 4px 12px -2.5px rgba(2, 31, 59, 0.65)',
})}
>
<Box
sx={{
flexGrow: 1,
display: 'flex',
alignItems: 'center',
ml: '-18px',
px: 0,
}}
>
<Typography variant="h6" color="primary" sx={{paddingLeft:"25px",paddingRight:"15px"}}>REQUEST.BOX</Typography>
<Box sx={{ display: { xs: 'none', md: 'flex' } }}>
<MenuItem
onClick={() => scrollToSection('home')}
sx={{ py: '6px', px: '12px' }}
>
<Typography variant="body2" color="text.primary">
Home
</Typography>
</MenuItem>
<MenuItem
onClick={() => scrollToSection('features')}
sx={{ py: '6px', px: '12px' }}
>
<Typography variant="body2" color="text.primary">
Features
</Typography>
</MenuItem>
<MenuItem
onClick={() => scrollToSection('beta-access')}
sx={{ py: '6px', px: '12px' }}
>
<Typography variant="body2" color="text.primary">
Beta Testing
</Typography>
</MenuItem>
<MenuItem
onClick={() => scrollToSection('faq')}
sx={{ py: '6px', px: '12px' }}
>
<Typography variant="body2" color="text.primary">
FAQ
</Typography>
</MenuItem>
<MenuItem
sx={{ py: '6px', px: '12px' }}
>
<Button href='https://discord.gg/hgcH4mvxFg'
target='_blank' variant="outlined" size="small">
Discord
</Button>
</MenuItem>
</Box>
</Box>
<Box
sx={{
display: { xs: 'none', md: 'flex' },
gap: 0.5,
alignItems: 'center',
}}
>
{(user ? (
<Button
color="secondary"
variant="contained"
size="small"
component="a"
href="/api/auth/login"
startIcon={<OpenInNew />}
>
Dashboard
</Button>
) : (
<Box>
<Button
color="primary"
variant="text"
size="small"
component="a"
href="/api/auth/login"
>
Sign in
</Button>
<Button
color="primary"
variant="contained"
size="small"
component="a"
href="/api/auth/login"
>
Sign up
</Button>
</Box>
)
)}
</Box>
<Box sx={{ display: { sm: '', md: 'none' } }}>
<Button
variant="text"
color="primary"
aria-label="menu"
onClick={toggleDrawer(true)}
sx={{ minWidth: '30px', p: '4px' }}
>
<MenuIcon />
</Button>
<Drawer anchor="right" open={open} onClose={toggleDrawer(false)}>
<Box
sx={{
minWidth: '60dvw',
p: 2,
backgroundColor: 'background.paper',
flexGrow: 1,
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'end',
flexGrow: 1,
}}
>
</Box>
<MenuItem onClick={() => scrollToSection('features')}>
Features
</MenuItem>
<MenuItem onClick={() => scrollToSection('testimonials')}>
Testimonials
</MenuItem>
<MenuItem onClick={() => scrollToSection('highlights')}>
Highlights
</MenuItem>
<MenuItem onClick={() => scrollToSection('pricing')}>
Pricing
</MenuItem>
<MenuItem onClick={() => scrollToSection('faq')}>FAQ</MenuItem>
<Divider />
<MenuItem>
<Button
color="primary"
variant="contained"
component="a"
href="/material-ui/getting-started/templates/sign-up/"
target="_blank"
sx={{ width: '100%' }}
>
Sign up
</Button>
</MenuItem>
<MenuItem>
<Button
color="primary"
variant="outlined"
component="a"
href="/material-ui/getting-started/templates/sign-in/"
target="_blank"
sx={{ width: '100%' }}
>
Sign in
</Button>
</MenuItem>
</Box>
</Drawer>
</Box>
</Toolbar>
</Container>
</AppBar>
</div>
);
}
export default AppAppBar;

68
components/BetaAccess.tsx Normal file
View File

@ -0,0 +1,68 @@
import * as React from 'react';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import Container from '@mui/material/Container';
import Button from '@mui/material/Button';
import { useMediaQuery } from '@mui/material';
import { useTheme } from '@mui/system';
import { OpenInNew } from '@mui/icons-material';
const whiteLogos = [
'https://assets-global.website-files.com/61ed56ae9da9fd7e0ef0a967/6560628e8573c43893fe0ace_Sydney-white.svg',
'https://assets-global.website-files.com/61ed56ae9da9fd7e0ef0a967/655f4d520d0517ae8e8ddf13_Bern-white.svg',
'https://assets-global.website-files.com/61ed56ae9da9fd7e0ef0a967/655f46794c159024c1af6d44_Montreal-white.svg',
'https://assets-global.website-files.com/61ed56ae9da9fd7e0ef0a967/61f12e891fa22f89efd7477a_TerraLight.svg',
'https://assets-global.website-files.com/61ed56ae9da9fd7e0ef0a967/6560a09d1f6337b1dfed14ab_colorado-white.svg',
'https://assets-global.website-files.com/61ed56ae9da9fd7e0ef0a967/655f5caa77bf7d69fb78792e_Ankara-white.svg',
];
const darkLogos = [
'https://assets-global.website-files.com/61ed56ae9da9fd7e0ef0a967/6560628889c3bdf1129952dc_Sydney-black.svg',
'https://assets-global.website-files.com/61ed56ae9da9fd7e0ef0a967/655f4d4d8b829a89976a419c_Bern-black.svg',
'https://assets-global.website-files.com/61ed56ae9da9fd7e0ef0a967/655f467502f091ccb929529d_Montreal-black.svg',
'https://assets-global.website-files.com/61ed56ae9da9fd7e0ef0a967/61f12e911fa22f2203d7514c_TerraDark.svg',
'https://assets-global.website-files.com/61ed56ae9da9fd7e0ef0a967/6560a0990f3717787fd49245_colorado-black.svg',
'https://assets-global.website-files.com/61ed56ae9da9fd7e0ef0a967/655f5ca4e548b0deb1041c33_Ankara-black.svg',
];
const logoStyle = {
width: '64px',
opacity: 0.3,
};
export default function BetaAccess() {
const theme = useTheme();
const isSmallScreen = useMediaQuery('(max-width:600px)');
const columns = isSmallScreen ? 1 : 3;
const logos = theme.palette.mode === 'light' ? darkLogos : whiteLogos;
return (
<Container
id="beta-access"
sx={{
pt: { xs: 4, sm: 12 },
pb: { xs: 8, sm: 16 },
position: 'relative',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: { xs: 3, sm: 6 },
}}
>
<Box
sx={{
width: { sm: '100%', md: '60%' },
textAlign: { sm: 'left', md: 'center' },
}}
>
<Typography component="h2" variant="h4" color="text.primary">
Founders Club
</Typography>
<Typography variant="body1" color="text.secondary" sx={{marginTop:"3%"}}>
Join the discord to get access to the beta and help shape the future of Request.Box. Founders club members will receive perks and early access to features. They will also vote in special community polls that influence the platforms development.
</Typography>
<Button color="primary" variant="contained" href="https://discord.gg/8v6j6j6C" target="_blank" rel="noopener" startIcon={<OpenInNew/>} sx={{marginTop:"3%"}}>OPEN DISCORD</Button>
</Box>
</Container>
);
}

140
components/FAQ.tsx Normal file
View File

@ -0,0 +1,140 @@
import * as React from 'react';
import Accordion from '@mui/material/Accordion';
import AccordionDetails from '@mui/material/AccordionDetails';
import AccordionSummary from '@mui/material/AccordionSummary';
import Box from '@mui/material/Box';
import Container from '@mui/material/Container';
import Link from '@mui/material/Link';
import Typography from '@mui/material/Typography';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
export default function FAQ() {
const [expanded, setExpanded] = React.useState<string | false>(false);
const handleChange =
(panel: string) => (event: React.SyntheticEvent, isExpanded: boolean) => {
setExpanded(isExpanded ? panel : false);
};
return (
<Container
id="faq"
sx={{
pt: { xs: 4, sm: 12 },
pb: { xs: 8, sm: 16 },
position: 'relative',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: { xs: 3, sm: 6 },
}}
>
<Typography
component="h2"
variant="h4"
color="text.primary"
sx={{
width: { sm: '100%', md: '60%' },
textAlign: { sm: 'left', md: 'center' },
}}
>
Frequently asked questions
</Typography>
<Box sx={{ width: '100%' }}>
<Accordion
expanded={expanded === 'panel1'}
onChange={handleChange('panel1')}
>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1d-content"
id="panel1d-header"
>
<Typography component="h3" variant="subtitle2">
What if I am banned on Stripe?
</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography
variant="body2"
gutterBottom
sx={{ maxWidth: { sm: '100%', md: '70%' } }}
>
You can reach out to our customer support on discord. We will help you figure out a solution tailored to your situation.
</Typography>
</AccordionDetails>
</Accordion>
<Accordion
expanded={expanded === 'panel2'}
onChange={handleChange('panel2')}
>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel2d-content"
id="panel2d-header"
>
<Typography component="h3" variant="subtitle2">
What happens if I dont like the art the artist provided?
</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography
variant="body2"
gutterBottom
sx={{ maxWidth: { sm: '100%', md: '70%' } }}
>
There are no refunds what so ever on this platform. We are not responsible for the art that is provided by the artist. We are simply a platform that connects artists with clients. We are not responsible for the quality of the art that is provided by the artist.
</Typography>
</AccordionDetails>
</Accordion>
<Accordion
expanded={expanded === 'panel3'}
onChange={handleChange('panel3')}
>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel3d-content"
id="panel3d-header"
>
<Typography component="h3" variant="subtitle2">
What makes your product stand out from others in the market?
</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography
variant="body2"
gutterBottom
sx={{ maxWidth: { sm: '100%', md: '70%' } }}
>
We provide support for the artists incase of chargebacks and other problems caused by problematic clients.
</Typography>
</AccordionDetails>
</Accordion>
<Accordion
expanded={expanded === 'panel4'}
onChange={handleChange('panel4')}
>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel4d-content"
id="panel4d-header"
>
<Typography component="h3" variant="subtitle2">
What countries are supported on the platforms for clients or for artists?
</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography
variant="body2"
gutterBottom
sx={{ maxWidth: { sm: '100%', md: '70%' } }}
>
This list will be changing often. We currently support all countries that Stripe supports. We are working on adding more payment processors to support more countries.
</Typography>
</AccordionDetails>
</Accordion>
</Box>
</Container>
);
}

99
components/Footer.tsx Normal file
View File

@ -0,0 +1,99 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Container from '@mui/material/Container';
import IconButton from '@mui/material/IconButton';
import Link from '@mui/material/Link';
import Stack from '@mui/material/Stack';
import TextField from '@mui/material/TextField';
import Typography from '@mui/material/Typography';
import FacebookIcon from '@mui/icons-material/GitHub';
import LinkedInIcon from '@mui/icons-material/LinkedIn';
import TwitterIcon from '@mui/icons-material/X';
const logoStyle = {
width: '140px',
height: 'auto',
};
function Copyright() {
return (
<Typography variant="body2" color="text.secondary" mt={1}>
{'Copyright © '}
<Link href="https://mui.com/">Request.Box&nbsp;</Link>
{new Date().getFullYear()}
</Typography>
);
}
export default function Footer() {
return (
<Container
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: { xs: 4, sm: 8 },
py: { xs: 8, sm: 10 },
textAlign: { sm: 'center', md: 'left' },
}}
>
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
pt: { xs: 4, sm: 8 },
width: '100%',
}}
>
<div>
<Link color="text.secondary" href="#">
Privacy Policy
</Link>
<Typography display="inline" sx={{ mx: 0.5, opacity: 0.5 }}>
&nbsp;&nbsp;
</Typography>
<Link color="text.secondary" href="#">
Terms of Service
</Link>
<Copyright />
</div>
<Stack
direction="row"
justifyContent="left"
spacing={1}
useFlexGap
sx={{
color: 'text.secondary',
}}
>
<IconButton
color="inherit"
href="https://github.com/mui"
aria-label="GitHub"
sx={{ alignSelf: 'center' }}
>
<FacebookIcon />
</IconButton>
<IconButton
color="inherit"
href="https://twitter.com/MaterialUI"
aria-label="X"
sx={{ alignSelf: 'center' }}
>
<TwitterIcon />
</IconButton>
<IconButton
color="inherit"
href="https://www.linkedin.com/company/mui/"
aria-label="LinkedIn"
sx={{ alignSelf: 'center' }}
>
<LinkedInIcon />
</IconButton>
</Stack>
</Box>
</Container>
);
}

82
components/Hero.tsx Normal file
View File

@ -0,0 +1,82 @@
import * as React from 'react';
import { alpha } from '@mui/material';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Container from '@mui/material/Container';
import Link from '@mui/material/Link';
import Stack from '@mui/material/Stack';
import TextField from '@mui/material/TextField';
import Typography from '@mui/material/Typography';
export default function Hero() {
return (
<Box
id="home"
sx={(theme) => ({
width: '100%',
backgroundImage:
theme.palette.mode === 'light'
? 'linear-gradient(180deg, #CEE5FD, #FFF)'
: 'linear-gradient(#02294F, #090E10)',
backgroundSize: '100% 20%',
backgroundRepeat: 'no-repeat',
})}
>
<Container
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
pt: { xs: 14, sm: 20 },
pb: { xs: 8, sm: 12 },
}}
>
<Stack spacing={2} useFlexGap sx={{ width: { xs: '100%', sm: '70%' } }}>
<Typography
component="h2"
variant="h2"
sx={{
display: 'flex',
flexDirection: { xs: 'column', md: 'row' },
alignSelf: 'center',
textAlign: 'center',
}}
>
Artists are&nbsp;
<Typography
component="span"
variant="h2"
sx={{
color: (theme) =>
theme.palette.mode === 'light' ? 'primary.main' : 'primary.light',
}}
>
protected.
</Typography>
</Typography>
<Typography variant="body1" textAlign="center" color="text.secondary">
We take a 13.5% precentage of all transactions that go through the platform. Stripe takes a 2.9% and 30 cents per transaction. We intend to take another 3.5% and add it to a fund. The intention of this fund will be to pay for claims that artists make for charge backs against their accounts and other such issues. The funds may be appropriated for other on platform enhancements that are voted in through community polls . The rest of the transaction fee will go to the platform and will be reinvested into the software and used to compensate the team.
</Typography>
<Stack
direction={{ xs: 'column', sm: 'row' }}
alignSelf="center"
spacing={1}
useFlexGap
sx={{ pt: 2, width: { xs: '100%', sm: 'auto' } }}
>
<Button variant="contained" color="primary">
Become an artist
</Button>
</Stack>
<Typography variant="caption" textAlign="center" sx={{ opacity: 0.8 }}>
By clicking &quot;Become an artist&quot; you agree to our&nbsp;
<Link href="#" color="primary">
Terms & Conditions
</Link>
.
</Typography>
</Stack>
</Container>
</Box>
);
}

122
components/Highlights.tsx Normal file
View File

@ -0,0 +1,122 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import Card from '@mui/material/Card';
import Container from '@mui/material/Container';
import Grid from '@mui/material/Grid';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import AutoFixHighRoundedIcon from '@mui/icons-material/AutoFixHighRounded';
import ConstructionRoundedIcon from '@mui/icons-material/ConstructionRounded';
import QueryStatsRoundedIcon from '@mui/icons-material/QueryStatsRounded';
import SettingsSuggestRoundedIcon from '@mui/icons-material/SettingsSuggestRounded';
import SupportAgentRoundedIcon from '@mui/icons-material/SupportAgentRounded';
import ThumbUpAltRoundedIcon from '@mui/icons-material/ThumbUpAltRounded';
import { CreditCard, Lock, MoneyRounded } from '@mui/icons-material';
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
const items = [
{
icon: <VisibilityOffIcon />,
title: 'Refund Policy/Artist Protection',
description:
'Payments are made upfront with no refunds. No delivery dates or unwanted communication with the artist. Any chargebacks can be disputed with evidence.',
},
{
icon: <CreditCard />,
title: 'Multiple Payment Platforms',
description:
'We support credit cards, google pay, and apple pay. More payment providers are coming soon. These are subject to change! All transactions on the platform show up as "Request.Box Request".',
},
{
icon: <AutoFixHighRoundedIcon />,
title: 'Skeb-like System',
description:
'Requests are made with a message, reference material, and amount of money. Artists can accept or decline the request.',
},
{
icon: <QueryStatsRoundedIcon />,
title: 'Payout Management',
description:
'Manage information about how you recieve your payments and view statistics about them in a user friendly dashboard',
},
{
icon: <SupportAgentRoundedIcon />,
title: 'Reliable support',
description:
'Get support directly from the developers and other staff members in the community discord.',
},
{
icon: <ThumbUpAltRoundedIcon />,
title: 'Small Business',
description:
'Software and its community is developed and maintained by its developer and founder.',
},
];
export default function Highlights() {
return (
<Box
id="highlights"
sx={{
pt: { xs: 4, sm: 12 },
pb: { xs: 8, sm: 16 },
color: 'white',
bgcolor: '#06090a',
}}
>
<Container
sx={{
position: 'relative',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: { xs: 3, sm: 6 },
}}
>
<Box
sx={{
width: { sm: '100%', md: '60%' },
textAlign: { sm: 'left', md: 'center' },
}}
>
<Typography component="h2" variant="h4">
Highlights
</Typography>
<Typography variant="body1" sx={{ color: 'grey.400' }}>
Explore why our product stands out: we keep the artist in mind at all times, and we are always looking for ways to improve the platform.
</Typography>
</Box>
<Grid container spacing={2.5}>
{items.map((item, index) => (
<Grid item xs={12} sm={6} md={4} key={index}>
<Stack
direction="column"
color="inherit"
component={Card}
spacing={1}
useFlexGap
sx={{
p: 3,
height: '100%',
border: '1px solid',
borderColor: 'grey.800',
background: 'transparent',
backgroundColor: 'grey.900',
}}
>
<Box sx={{ opacity: '50%' }}>{item.icon}</Box>
<div>
<Typography fontWeight="medium" gutterBottom>
{item.title}
</Typography>
<Typography variant="body2" sx={{ color: 'grey.400' }}>
{item.description}
</Typography>
</div>
</Stack>
</Grid>
))}
</Grid>
</Container>
</Box>
);
}

219
components/Pricing.tsx Normal file
View File

@ -0,0 +1,219 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Card from '@mui/material/Card';
import Chip from '@mui/material/Chip';
import CardActions from '@mui/material/CardActions';
import CardContent from '@mui/material/CardContent';
import Container from '@mui/material/Container';
import Divider from '@mui/material/Divider';
import Grid from '@mui/material/Grid';
import Typography from '@mui/material/Typography';
import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome';
import CheckCircleRoundedIcon from '@mui/icons-material/CheckCircleRounded';
const tiers = [
{
title: 'Free',
price: '0',
description: [
'10 users included',
'2 GB of storage',
'Help center access',
'Email support',
],
buttonText: 'Sign up for free',
buttonVariant: 'outlined',
},
{
title: 'Professional',
subheader: 'Recommended',
price: '15',
description: [
'20 users included',
'10 GB of storage',
'Help center access',
'Priority email support',
'Dedicated team',
'Best deals',
],
buttonText: 'Start now',
buttonVariant: 'contained',
},
{
title: 'Enterprise',
price: '30',
description: [
'50 users included',
'30 GB of storage',
'Help center access',
'Phone & email support',
],
buttonText: 'Contact us',
buttonVariant: 'outlined',
},
];
export default function Pricing() {
return (
<Container
id="pricing"
sx={{
pt: { xs: 4, sm: 12 },
pb: { xs: 8, sm: 16 },
position: 'relative',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: { xs: 3, sm: 6 },
}}
>
<Box
sx={{
width: { sm: '100%', md: '60%' },
textAlign: { sm: 'left', md: 'center' },
}}
>
<Typography component="h2" variant="h4" color="text.primary">
Pricing
</Typography>
<Typography variant="body1" color="text.secondary">
Quickly build an effective pricing table for your potential customers with
this layout. <br />
It&apos;s built with default Material UI components with little
customization.
</Typography>
</Box>
<Grid container spacing={3} alignItems="center" justifyContent="center">
{tiers.map((tier) => (
<Grid
item
key={tier.title}
xs={12}
sm={tier.title === 'Enterprise' ? 12 : 6}
md={4}
>
<Card
sx={{
p: 2,
display: 'flex',
flexDirection: 'column',
gap: 4,
border: tier.title === 'Professional' ? '1px solid' : undefined,
borderColor:
tier.title === 'Professional' ? 'primary.main' : undefined,
background:
tier.title === 'Professional'
? 'linear-gradient(#033363, #021F3B)'
: undefined,
}}
>
<CardContent>
<Box
sx={{
mb: 1,
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
color:
tier.title === 'Professional' ? 'primary.contrastText' : '',
}}
>
<Typography component="h3" variant="h6">
{tier.title}
</Typography>
{tier.title === 'Professional' && (
<Chip
icon={<AutoAwesomeIcon />}
label={tier.subheader}
size="small"
sx={{
background: (theme) =>
theme.palette.mode === 'light' ? '' : 'none',
backgroundColor: 'primary.contrastText',
'& .MuiChip-label': {
color: 'primary.dark',
},
'& .MuiChip-icon': {
color: 'primary.dark',
},
}}
/>
)}
</Box>
<Box
sx={{
display: 'flex',
alignItems: 'baseline',
color:
tier.title === 'Professional'
? 'primary.contrastText'
: undefined,
}}
>
<Typography component="h3" variant="h2">
${tier.price}
</Typography>
<Typography component="h3" variant="h6">
&nbsp; per month
</Typography>
</Box>
<Divider
sx={{
my: 2,
opacity: 0.2,
borderColor: 'grey.500',
}}
/>
{tier.description.map((line) => (
<Box
key={line}
sx={{
py: 1,
display: 'flex',
gap: 1.5,
alignItems: 'center',
}}
>
<CheckCircleRoundedIcon
sx={{
width: 20,
color:
tier.title === 'Professional'
? 'primary.light'
: 'primary.main',
}}
/>
<Typography
component="text"
variant="subtitle2"
sx={{
color:
tier.title === 'Professional'
? 'primary.contrastText'
: undefined,
}}
>
{line}
</Typography>
</Box>
))}
</CardContent>
<CardActions>
<Button
fullWidth
variant={tier.buttonVariant as 'outlined' | 'contained'}
component="a"
href="/material-ui/getting-started/templates/checkout/"
target="_blank"
>
{tier.buttonText}
</Button>
</CardActions>
</Card>
</Grid>
))}
</Grid>
</Container>
);
}

13
components/RootSvg.tsx Normal file
View File

@ -0,0 +1,13 @@
import { styled, Theme } from '@mui/material/styles';
import { SxProps } from '@mui/system';
export type RootSvgProps<P = unknown> = Omit<React.SVGProps<SVGSVGElement>, 'ref'> & {
sx?: SxProps<Theme>;
ref?: React.Ref<SVGSVGElement>;
} & P;
const Svg = styled('svg')({
verticalAlign: 'bottom',
});
export default Svg;

View File

@ -0,0 +1,21 @@
import * as React from 'react';
import RootSvg, { RootSvgProps } from './RootSvg';
function SvgMaterialDesign(props: RootSvgProps) {
return (
<RootSvg
xmlns="http://www.w3.org/2000/svg"
width={24}
height={24}
viewBox="0 0 24 24"
fill="none"
{...props}
>
<circle cx={12} cy={12} r={12} fill="#737373" />
<path fill="#BDBDBD" d="M4 4h16v16H4z" />
<path fillRule="evenodd" clipRule="evenodd" d="M12 20l8-16H4l8 16z" fill="#fff" />
</RootSvg>
);
}
export default SvgMaterialDesign;

View File

@ -0,0 +1,67 @@
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 ? (
<Grid item xs={12} sm={12} lg={4} sx={{ textAlign: "center" ,paddingTop:"1rem"}}>
<Card sx={{ minWidth: 275 }}>
<CardContent>
<Typography variant="h5" gutterBottom>
Request Status
</Typography>
{(sellerRequestData["accepted"] ? (
<Typography variant="body2" color="text.warning" component="div">Accepted</Typography>
) : (
<Typography variant="h6" color="text.warning" component="div">Pending</Typography>
))}
<Typography variant="body2" color="text.secondary" component="div">Request submitted on {formattedTime ?? ''}</Typography>
</CardContent>
</Card>
</Grid>) : (
<Box sx={{textAlign:"center", paddingTop:"5%"}}>
<Typography variant="h4" sx={{textAlign:"center"}}>
Loading
</Typography>
<Box sx={{ paddingTop: 5 }} />
<CircularProgress />
</Box>
))
)
}
export default ArtistDashboardRequest

View File

@ -13,7 +13,7 @@ const ArtistPortfolio = ({artistId}) => {
setPortfolioData(data); setPortfolioData(data);
setLoading(false); setLoading(false);
} }
////console.log(portfolioData) (portfolioData)
getData(); getData();
}, []); }, []);
return ( return (

View File

@ -45,9 +45,8 @@ const EditableArtistPortfolio = ({ artistId }) => {
</Box> </Box>
) : ) :
( (
(portfolioData.length > 0 ?(<>
<Grid container spacing={2} sm={12} sx={{ padding: 4 }}> <Grid container spacing={2} sm={12}>
<Grid item xs={12} sm={12} sx={{ textAlign: "center" }}> <Grid item xs={12} sm={12} sx={{ textAlign: "center" }}>
<input <input
id="portfolioUploadInput" id="portfolioUploadInput"
@ -65,40 +64,19 @@ const EditableArtistPortfolio = ({ artistId }) => {
sx={{width:"100%"}} sx={{width:"100%"}}
startIcon={<FileOpenIcon />} startIcon={<FileOpenIcon />}
> >
Add Image {(portfolioData.length > 0 ? "Upload Another Portfolio Image" : "Upload Your First Portfolio Image")}
</Button> </Button>
</label> </label>
</Grid> </Grid>
<Grid item xs={12} sm={12}>
<ImageList cols={2} rowHeight={200} sx={{ height: 400, width:"100%" }}>
{portfolioData.map((item) => (
<EditableArtistPortfolioImage artistId={artistId} itemId={item.id} reload={getData}/>
))}
</ImageList>
</Grid>
</Grid> </Grid>
<ImageList cols={2} rowHeight={200} sx={{ height: 400, width:"100%" }}>
{portfolioData.map((item) => (
<EditableArtistPortfolioImage artistId={artistId} itemId={item.id} />
))}
</ImageList>
</>
) : (
<Box sx={{ textAlign: "center" }}>
<input
id="portfolioUploadInput"
style={{ display: 'none' }}
accept="image/*"
type="file"
onChange={handlePortfolioUploadImageChange}
/>
<label htmlFor="portfolioUploadInput">
<Button
fullWidth
variant='outlined'
component="span"
size="small"
sx={{width:"100%"}}
startIcon={<FileOpenIcon />}
>
Upload Your First Portfolio Image
</Button>
</label>
</Box>
))
) )
) )
} }

View File

@ -8,18 +8,22 @@ import { CircularProgress, ImageListItemBar } from '@mui/material';
import { IconButton } from '@mui/material'; import { IconButton } from '@mui/material';
const EditableArtistPortfolioImage = ({artistId,itemId}) => { const EditableArtistPortfolioImage = ({artistId,itemId,reload}) => {
const [loaded, setLoaded] = useState(false); const [loaded, setLoaded] = useState(false);
const [deleting, setDeleting] = useState(false);
const handleImageLoaded = () => { const handleImageLoaded = () => {
setLoaded(true); setLoaded(true);
}; };
const deleteButton = () => { const deleteButton = () => {
setDeleting(true);
fetch('/api/artist/portfolio/'+itemId+"/delete", { fetch('/api/artist/portfolio/'+itemId+"/delete", {
method: 'DELETE' method: 'DELETE'
}).then(response => }).then(response => {
window.location.reload()); reload().then(data => {
})
})
} }
return ( return (

View File

@ -22,7 +22,7 @@ const Layout = ({ user, loading = false, children }: LayoutProps) => {
<style jsx>{` <style jsx>{`
.container { .container {
max-width: 42rem; max-width: 82rem;
margin: 1.5rem auto; margin: 1.5rem auto;
} }
`}</style> `}</style>

116
package-lock.json generated
View File

@ -11,6 +11,7 @@
"@fontsource/roboto": "^5.0.8", "@fontsource/roboto": "^5.0.8",
"@lupus-ai/mui-currency-textfield": "^1.0.3", "@lupus-ai/mui-currency-textfield": "^1.0.3",
"@mui/icons-material": "^5.15.6", "@mui/icons-material": "^5.15.6",
"@mui/lab": "^5.0.0-alpha.165",
"@mui/material": "^5.15.6", "@mui/material": "^5.15.6",
"@mui/x-data-grid": "^6.19.4", "@mui/x-data-grid": "^6.19.4",
"@mui/x-date-pickers": "^6.19.4", "@mui/x-date-pickers": "^6.19.4",
@ -489,6 +490,77 @@
} }
} }
}, },
"node_modules/@mui/lab": {
"version": "5.0.0-alpha.165",
"resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.165.tgz",
"integrity": "sha512-8/zJStT10nh9yrAzLOPTICGhpf5YiGp/JpM0bdTP7u5AE+YT+X2u6QwMxuCrVeW8/WVLAPFg0vtzyfgPcN5T7g==",
"dependencies": {
"@babel/runtime": "^7.23.9",
"@mui/base": "5.0.0-beta.36",
"@mui/system": "^5.15.9",
"@mui/types": "^7.2.13",
"@mui/utils": "^5.15.9",
"clsx": "^2.1.0",
"prop-types": "^15.8.1"
},
"engines": {
"node": ">=12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
},
"peerDependencies": {
"@emotion/react": "^11.5.0",
"@emotion/styled": "^11.3.0",
"@mui/material": ">=5.15.0",
"@types/react": "^17.0.0 || ^18.0.0",
"react": "^17.0.0 || ^18.0.0",
"react-dom": "^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@emotion/react": {
"optional": true
},
"@emotion/styled": {
"optional": true
},
"@types/react": {
"optional": true
}
}
},
"node_modules/@mui/lab/node_modules/@mui/base": {
"version": "5.0.0-beta.36",
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.36.tgz",
"integrity": "sha512-6A8fYiXgjqTO6pgj31Hc8wm1M3rFYCxDRh09dBVk0L0W4cb2lnurRJa3cAyic6hHY+we1S58OdGYRbKmOsDpGQ==",
"dependencies": {
"@babel/runtime": "^7.23.9",
"@floating-ui/react-dom": "^2.0.8",
"@mui/types": "^7.2.13",
"@mui/utils": "^5.15.9",
"@popperjs/core": "^2.11.8",
"clsx": "^2.1.0",
"prop-types": "^15.8.1"
},
"engines": {
"node": ">=12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
},
"peerDependencies": {
"@types/react": "^17.0.0 || ^18.0.0",
"react": "^17.0.0 || ^18.0.0",
"react-dom": "^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@mui/material": { "node_modules/@mui/material": {
"version": "5.15.6", "version": "5.15.6",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.6.tgz", "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.6.tgz",
@ -534,12 +606,12 @@
} }
}, },
"node_modules/@mui/private-theming": { "node_modules/@mui/private-theming": {
"version": "5.15.6", "version": "5.15.9",
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.6.tgz", "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.9.tgz",
"integrity": "sha512-ZBX9E6VNUSscUOtU8uU462VvpvBS7eFl5VfxAzTRVQBHflzL+5KtnGrebgf6Nd6cdvxa1o0OomiaxSKoN2XDmg==", "integrity": "sha512-/aMJlDOxOTAXyp4F2rIukW1O0anodAMCkv1DfBh/z9vaKHY3bd5fFf42wmP+0GRmwMinC5aWPpNfHXOED1fEtg==",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.23.8", "@babel/runtime": "^7.23.9",
"@mui/utils": "^5.15.6", "@mui/utils": "^5.15.9",
"prop-types": "^15.8.1" "prop-types": "^15.8.1"
}, },
"engines": { "engines": {
@ -560,13 +632,13 @@
} }
}, },
"node_modules/@mui/styled-engine": { "node_modules/@mui/styled-engine": {
"version": "5.15.6", "version": "5.15.9",
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.6.tgz", "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.9.tgz",
"integrity": "sha512-KAn8P8xP/WigFKMlEYUpU9z2o7jJnv0BG28Qu1dhNQVutsLVIFdRf5Nb+0ijp2qgtcmygQ0FtfRuXv5LYetZTg==", "integrity": "sha512-NRKtYkL5PZDH7dEmaLEIiipd3mxNnQSO+Yo8rFNBNptY8wzQnQ+VjayTq39qH7Sast5cwHKYFusUrQyD+SS4Og==",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.23.8", "@babel/runtime": "^7.23.9",
"@emotion/cache": "^11.11.0", "@emotion/cache": "^11.11.0",
"csstype": "^3.1.2", "csstype": "^3.1.3",
"prop-types": "^15.8.1" "prop-types": "^15.8.1"
}, },
"engines": { "engines": {
@ -591,17 +663,17 @@
} }
}, },
"node_modules/@mui/system": { "node_modules/@mui/system": {
"version": "5.15.6", "version": "5.15.9",
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.6.tgz", "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.9.tgz",
"integrity": "sha512-J01D//u8IfXvaEHMBQX5aO2l7Q+P15nt96c4NskX7yp5/+UuZP8XCQJhtBtLuj+M2LLyXHYGmCPeblsmmscP2Q==", "integrity": "sha512-SxkaaZ8jsnIJ77bBXttfG//LUf6nTfOcaOuIgItqfHv60ZCQy/Hu7moaob35kBb+guxVJnoSZ+7vQJrA/E7pKg==",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.23.8", "@babel/runtime": "^7.23.9",
"@mui/private-theming": "^5.15.6", "@mui/private-theming": "^5.15.9",
"@mui/styled-engine": "^5.15.6", "@mui/styled-engine": "^5.15.9",
"@mui/types": "^7.2.13", "@mui/types": "^7.2.13",
"@mui/utils": "^5.15.6", "@mui/utils": "^5.15.9",
"clsx": "^2.1.0", "clsx": "^2.1.0",
"csstype": "^3.1.2", "csstype": "^3.1.3",
"prop-types": "^15.8.1" "prop-types": "^15.8.1"
}, },
"engines": { "engines": {
@ -643,11 +715,11 @@
} }
}, },
"node_modules/@mui/utils": { "node_modules/@mui/utils": {
"version": "5.15.6", "version": "5.15.9",
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.6.tgz", "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.9.tgz",
"integrity": "sha512-qfEhf+zfU9aQdbzo1qrSWlbPQhH1nCgeYgwhOVnj9Bn39shJQitEnXpSQpSNag8+uty5Od6PxmlNKPTnPySRKA==", "integrity": "sha512-yDYfr61bCYUz1QtwvpqYy/3687Z8/nS4zv7lv/ih/6ZFGMl1iolEvxRmR84v2lOYxlds+kq1IVYbXxDKh8Z9sg==",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.23.8", "@babel/runtime": "^7.23.9",
"@types/prop-types": "^15.7.11", "@types/prop-types": "^15.7.11",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
"react-is": "^18.2.0" "react-is": "^18.2.0"

View File

@ -12,6 +12,7 @@
"@fontsource/roboto": "^5.0.8", "@fontsource/roboto": "^5.0.8",
"@lupus-ai/mui-currency-textfield": "^1.0.3", "@lupus-ai/mui-currency-textfield": "^1.0.3",
"@mui/icons-material": "^5.15.6", "@mui/icons-material": "^5.15.6",
"@mui/lab": "^5.0.0-alpha.165",
"@mui/material": "^5.15.6", "@mui/material": "^5.15.6",
"@mui/x-data-grid": "^6.19.4", "@mui/x-data-grid": "^6.19.4",
"@mui/x-date-pickers": "^6.19.4", "@mui/x-date-pickers": "^6.19.4",

View File

@ -35,7 +35,7 @@ export default withApiAuthRequired(async function handler(req, res) {
body: await createBlobFromFile(file[0].filepath) // Don't set Content-Type, FormData will handle it body: await createBlobFromFile(file[0].filepath) // Don't set Content-Type, FormData will handle it
}); });
//console.log(response) (response)
if (!response.ok) { if (!response.ok) {
const errorData = await response.json(); const errorData = await response.json();
throw new Error(errorData.message || 'Failed to upload file'); throw new Error(errorData.message || 'Failed to upload file');

View File

@ -1,14 +1,13 @@
export default async function handler(req, res ): Promise<any> { export default async function handler(req, res ): Promise<any> {
const { sellerId } = req.query; const { sellerId } = req.query;
var url = process.env.NEXT_PUBLIC_API_URL+`/api/Discovery/Sellers/${sellerId}/Portfolio`; var url = process.env.NEXT_PUBLIC_API_URL+`/api/Discovery/Sellers/${sellerId}/Portfolio`;
////console.log(url) (url)
const response = await fetch(url); const response = await fetch(url);
console.log(response)
if (!response.ok) { if (!response.ok) {
throw new Error('Failed to fetch seller portfolio'); throw new Error('Failed to fetch seller portfolio');
} }
var result = await response.json(); var result = await response.json();
////console.log(result) (result)
res.status(200).json(result); res.status(200).json(result);
} }

View File

@ -4,15 +4,19 @@ import AppBar from '@mui/material/AppBar';
import Tabs from '@mui/material/Tabs'; import Tabs from '@mui/material/Tabs';
import Tab from '@mui/material/Tab'; import Tab from '@mui/material/Tab';
import Layout from "../components/layout"; import Layout from "../components/layout";
import { Grid, Button, Typography, TextField, Box, CircularProgress } from "@mui/material"; import { Grid, Button, Typography, TextField, Box, CircularProgress, IconButton } from "@mui/material";
import { useState, useEffect } from "react"; import { useState, useEffect,useRef } from "react";
import Card from '@mui/material/Card'; import Card from '@mui/material/Card';
import CardContent from '@mui/material/CardContent'; import CardContent from '@mui/material/CardContent';
import CardActions from '@mui/material/CardActions'; import CardActions from '@mui/material/CardActions';
import { styled } from '@mui/material/styles'; import { styled } from '@mui/material/styles';
import SwipeableViews from '../components/swipableView'; import SwipeableViews from '../components/swipableView';
import { DataGrid, GridColDef, GridValueGetterParams } from '@mui/x-data-grid'; import { DataGrid, GridColDef, GridValueGetterParams } from '@mui/x-data-grid';
import ThumbsUpDownIcon from '@mui/icons-material/ThumbsUpDown';
import EditableArtistPortfolio from "../components/editableArtistPortfolio"; import EditableArtistPortfolio from "../components/editableArtistPortfolio";
import Popover from '@mui/material/Popover';
import ArtistDashboardRequest from "../components/artistDashboardRequest";
@ -20,21 +24,16 @@ import EditableArtistPortfolio from "../components/editableArtistPortfolio";
const SellerDashoard = (ctx) => { const SellerDashoard = (ctx) => {
const { user, isLoading } = useUser(); const { user, isLoading } = useUser();
const [sellerRequestData, setSellerRequestData] = useState([]);
const [sellerData, setSellerData] = useState([]); const [sellerData, setSellerData] = useState([]);
const [loading, setLoading] = useState(true); // State for loading indicator const [loading, setLoading] = useState(true); // State for loading indicator
const [isOnboarded, setIsOnboarded] = useState(false); const [isOnboarded, setIsOnboarded] = useState(false);
const [onBoardUrl, setOnBoardUrl] = useState(""); const [onBoardUrl, setOnBoardUrl] = useState("");
const [tabValue, setTabValue] = useState(1); const [tabValue, setTabValue] = useState(1);
const getData = async () => { const getData = async () => {
const response = await fetch('/api/artist/profile'); const response = await fetch('/api/artist/profile');
const sellerProfile = await response.json(); const sellerProfile = await response.json();
setSellerData(sellerProfile); setSellerData(sellerProfile);
const requestResponse = await fetch('/api/artist/request', { method: "GET" });
const sellerRequest = await requestResponse.json();
setSellerRequestData(sellerRequest);
const onboardCheckRequest = await fetch('/api/artist/onboarded', { method: "GET" }); const onboardCheckRequest = await fetch('/api/artist/onboarded', { method: "GET" });
const onboardCheckResponse = await onboardCheckRequest.json(); const onboardCheckResponse = await onboardCheckRequest.json();
setIsOnboarded(onboardCheckResponse["onboarded"]); setIsOnboarded(onboardCheckResponse["onboarded"]);
@ -45,6 +44,8 @@ const SellerDashoard = (ctx) => {
setLoading(false); // Once data is fetched, set loading to false setLoading(false); // Once data is fetched, set loading to false
} }
const handleChange = (event: React.SyntheticEvent, newValue: number) => { const handleChange = (event: React.SyntheticEvent, newValue: number) => {
setTabValue(newValue); setTabValue(newValue);
}; };
@ -92,11 +93,57 @@ const SellerDashoard = (ctx) => {
getData(); getData();
}, []); }, []);
const theme = useTheme(); const theme = useTheme();
const columns: GridColDef[] = [ const columns: GridColDef[] = [
{ field: 'requestor', headerName: 'User', width: 150 }, { field: 'requestor', headerName: 'User', width: 150 },
{ field: 'message', headerName: 'Message', width: 280 }, { field: 'message', headerName: 'Message', width: 280 },
{ field: 'amount', headerName: 'Amount', width: 125 }, { field: 'amount', headerName: 'Amount', width: 50 },
{
field: "action",
headerName: "Action",
sortable: false,
renderCell: (params) => {
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(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 (
<>
<Button ref={buttonRef} startIcon={<ThumbsUpDownIcon/>} color="success" onClick={handleClick}></Button>
<Popover
id={params["requestor"]+"-"+params["amount"]}
open={open}
anchorEl={buttonRef.current}
onClose={handleClose}
transformOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
>
<Button size="small" color="success" variant="contained" onClick={accept}>Accept</Button>
<Button size="small" color="error" variant="contained" onClick={decline}>Decline</Button>
</Popover>
</>
)
}
}
]; ];
const rows = [ const rows = [
{ id: 1, requestor: 'Snow', message: 'This is a test message!', amount: 35.00 }, { id: 1, requestor: 'Snow', message: 'This is a test message!', amount: 35.00 },
@ -111,36 +158,6 @@ const SellerDashoard = (ctx) => {
]; ];
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 payoutButton = () =>{
fetch('/api/artist/payout').then((response) => {
if (response.ok) {
fetch('/api/artist/request').then((requestResponse) => {
requestResponse.json().then((sellerRequest) => {
setSellerRequestData(sellerRequest);
});
});
}
});
}
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 ( return (
<> <>
@ -154,8 +171,7 @@ const SellerDashoard = (ctx) => {
</Box> </Box>
) : ( ) : (
<Layout user={user} loading={isLoading}> <Layout user={user} loading={isLoading}>
<Grid container spacing={2} sx={{ padding: 4 }}> <Grid container >
{(Object.keys(sellerData).length > 0 ? ( {(Object.keys(sellerData).length > 0 ? (
<> <>
<Grid item container sx={{ textAlign: "center" }}> <Grid item container sx={{ textAlign: "center" }}>
@ -172,95 +188,7 @@ const SellerDashoard = (ctx) => {
<Grid item xs={12} sm={2} sx={{ textAlign: "center" }}> <Grid item xs={12} sm={2} sx={{ textAlign: "center" }}>
</Grid> </Grid>
</Grid> </Grid>
{(Object.keys(sellerRequestData).length > 0 ? ( <ArtistDashboardRequest/>
<>
<Grid item xs={12} sm={12} sx={{ textAlign: "center" }}>
<Card sx={{ minWidth: 275, paddingTop: 2 }}>
<CardContent>
<Typography variant="h5" gutterBottom>
Request Status
</Typography>
{(sellerRequestData["accepted"] ? (
<Typography variant="body2" color="text.warning" component="div">Accepted</Typography>
) : (
<Typography variant="h6" color="text.warning" component="div">Pending</Typography>
))}
<Typography variant="body2" color="text.secondary" component="div">Request submitted on {formattedTime ?? ''}</Typography>
</CardContent>
<CardActions>
<Button color="primary" href="https://discord.gg/SAGBA3uTEF" target="_blank" size="small">Contact Us On Discord</Button>
</CardActions>
</Card>
</Grid>
<Grid item xs={12} sm={12}>
{(sellerRequestData["accepted"] ? (
<>
{(isOnboarded ? (<>
<Button sx={{ width: "50%" }} color="primary" variant="contained" href={onBoardUrl}>Payout Settings</Button>
<Button sx={{ width: "50%" }} color="secondary" variant="contained">Payout Portal</Button>
</>
) : (
<>
<Button sx={{ width: "50%" }} href={onBoardUrl} color="secondary" variant="contained">Payout Onboarding</Button>
<Button sx={{ width: "50%" }} color="secondary" variant="contained" disabled>Payout Portal</Button>
</>
))}
<Grid item container xs={12} sm={12} sx={{paddingTop:2}}>
<AppBar position="static">
<Tabs
value={tabValue}
onChange={handleChange}
indicatorColor="secondary"
textColor="inherit"
variant="fullWidth"
aria-label="full width tabs example"
>
<Tab label="New Requests" {...a11yProps(0)} />
<Tab label="Portfolio" {...a11yProps(1)} />
<Tab label="Ongoing Requests" {...a11yProps(2)} />
</Tabs>
</AppBar>
<SwipeableViews
index={tabValue}
onChangeIndex={handleChangeIndex}
>
<TabPanel value={tabValue} index={0} dir={theme.direction}>
<DataGrid
rows={rows}
columns={columns}
initialState={{
pagination: {
paginationModel: { page: 0, pageSize: 5 },
},
}}
pageSizeOptions={[5, 10]}
sx={{ width: '100%' }}
/>
</TabPanel>
<TabPanel value={tabValue} index={1} dir={theme.direction} >
<EditableArtistPortfolio artistId={sellerData["id"]}></EditableArtistPortfolio>
</TabPanel>
<TabPanel value={tabValue} index={2} dir={theme.direction}>
Item Three
</TabPanel>
</SwipeableViews>
</Grid>
</>
) : (
<></> ))}
</Grid>
</>
) : (
<>
<Grid item xs={12} sm={12} sx={{ textAlign: "center" }}>
{(Object.keys(sellerRequestData).length==0 || sellerRequestData["accepted"]==false ? (<><Button sx={{ width: "50%" }} color="secondary" onClick={requestButton} variant="contained">Request Artist Access</Button></>):(<></>))}
</Grid>
</>
))}
</> </>
) : ( ) : (

View File

@ -1,42 +1,91 @@
import * as React from 'react';
import { PaletteMode } from '@mui/material';
import CssBaseline from '@mui/material/CssBaseline';
import Box from '@mui/material/Box';
import Divider from '@mui/material/Divider';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import ToggleButton from '@mui/material/ToggleButton';
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
import AutoAwesomeRoundedIcon from '@mui/icons-material/AutoAwesomeRounded';
import SvgMaterialDesign from '../components/SvgMaterialDesign';
import AppAppBar from '../components/AppAppBar';
import Hero from '../components/Hero';
import Highlights from '../components/Highlights';
import Pricing from '../components/Pricing';
import BetaAccess from '../components/BetaAccess';
import FAQ from '../components/FAQ';
import Footer from '../components/Footer';
import { useUser } from "@auth0/nextjs-auth0/client"; import { useUser } from "@auth0/nextjs-auth0/client";
import Layout from "../components/layout"; const defaultTheme = createTheme({});
import { Typography, Box, CircularProgress } from '@mui/material';
import Artist from "../components/artist";
import { useEffect, useState } from "react";
const Home = () => { interface ToggleCustomThemeProps {
const [sellersData, setSellersData] = useState([]); showCustomTheme: Boolean;
const [loading, setLoading] = useState(true); // State for loading indicator toggleCustomTheme: () => void;
useEffect(() => { }
const getData = async () => {
const response = await fetch('/api/discovery/artists'); function ToggleCustomTheme({
const data = await response.json(); showCustomTheme,
setSellersData(data); toggleCustomTheme,
setLoading(false); }: ToggleCustomThemeProps) {
}
getData();
}, []);
const { user, isLoading } = useUser();
return ( return (
<Layout user={user} loading={isLoading}> <Box
{loading ? ( // Render loading indicator if loading is true sx={{
<Box sx={{textAlign:"center", paddingTop:20}}> display: 'flex',
<Typography variant="h4" sx={{textAlign:"center"}}> flexDirection: 'column',
Loading alignItems: 'center',
</Typography> width: '100dvw',
<Box sx={{ paddingTop: 5 }} /> position: 'fixed',
<CircularProgress /> bottom: 24,
</Box> }}
) : ( >
<> <ToggleButtonGroup
{sellersData.map((item) => ( color="primary"
<Artist user={user} artistId={item.id} /> exclusive
))} value={showCustomTheme}
</> onChange={toggleCustomTheme}
)} aria-label="Platform"
</Layout> sx={{
backgroundColor: 'background.default',
'& .Mui-selected': {
pointerEvents: 'none',
},
}}
>
<ToggleButton value>
<AutoAwesomeRoundedIcon sx={{ fontSize: '20px', mr: 1 }} />
Custom theme
</ToggleButton>
<ToggleButton value={false}>
<SvgMaterialDesign sx={{ fontSize: '20px', mr: 1 }} />
Material Design
</ToggleButton>
</ToggleButtonGroup>
</Box>
); );
}; }
// fast/cached SSR page export default function LandingPage() {
export default Home; const [showCustomTheme, setShowCustomTheme] = React.useState(true);
const { user, isLoading } = useUser();
const toggleCustomTheme = () => {
setShowCustomTheme((prev) => !prev);
};
return (
<ThemeProvider theme={defaultTheme}>
<CssBaseline />
<AppAppBar user={user} />
<Hero />
<Box sx={{ bgcolor: 'background.default' }}>
<Highlights />
<Divider />
<BetaAccess />
<Divider />
<FAQ />
<Footer />
</Box>
</ThemeProvider>
);
}