From 937faf18470301fb1138e0680274b5fd910cf7ff Mon Sep 17 00:00:00 2001 From: Damien Ostler Date: Thu, 15 Feb 2024 21:49:12 -0500 Subject: [PATCH] feat:landing page --- components/AppAppBar.tsx | 252 ++++++++++++++++++ components/BetaAccess.tsx | 68 +++++ components/FAQ.tsx | 140 ++++++++++ components/Footer.tsx | 99 +++++++ components/Hero.tsx | 82 ++++++ components/Highlights.tsx | 122 +++++++++ components/Pricing.tsx | 219 +++++++++++++++ components/RootSvg.tsx | 13 + components/SvgMaterialDesign.tsx | 21 ++ components/artistDashboardRequest.tsx | 67 +++++ components/artistPortfolio.tsx | 2 +- components/editableArtistPortfolio.tsx | 42 +-- components/editableArtistPortfolioImage.tsx | 10 +- components/layout.tsx | 2 +- package-lock.json | 116 ++++++-- package.json | 1 + pages/api/artist/portfolio.tsx | 2 +- .../discovery/artist/[sellerId]/portfolio.tsx | 5 +- pages/artistDashboard.tsx | 188 ++++--------- pages/index.tsx | 123 ++++++--- 20 files changed, 1344 insertions(+), 230 deletions(-) create mode 100644 components/AppAppBar.tsx create mode 100644 components/BetaAccess.tsx create mode 100644 components/FAQ.tsx create mode 100644 components/Footer.tsx create mode 100644 components/Hero.tsx create mode 100644 components/Highlights.tsx create mode 100644 components/Pricing.tsx create mode 100644 components/RootSvg.tsx create mode 100644 components/SvgMaterialDesign.tsx create mode 100644 components/artistDashboardRequest.tsx diff --git a/components/AppAppBar.tsx b/components/AppAppBar.tsx new file mode 100644 index 0000000..ec26910 --- /dev/null +++ b/components/AppAppBar.tsx @@ -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 ( +
+ + + ({ + 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)', + })} + > + + REQUEST.BOX + + scrollToSection('home')} + sx={{ py: '6px', px: '12px' }} + > + + Home + + + scrollToSection('features')} + sx={{ py: '6px', px: '12px' }} + > + + Features + + + scrollToSection('beta-access')} + sx={{ py: '6px', px: '12px' }} + > + + Beta Testing + + + scrollToSection('faq')} + sx={{ py: '6px', px: '12px' }} + > + + FAQ + + + + + + + + + {(user ? ( + + ) : ( + + + + + ) + )} + + + + + + + + scrollToSection('features')}> + Features + + scrollToSection('testimonials')}> + Testimonials + + scrollToSection('highlights')}> + Highlights + + scrollToSection('pricing')}> + Pricing + + scrollToSection('faq')}>FAQ + + + + + + + + + + + + + +
+ ); +} + +export default AppAppBar; diff --git a/components/BetaAccess.tsx b/components/BetaAccess.tsx new file mode 100644 index 0000000..1ac54e9 --- /dev/null +++ b/components/BetaAccess.tsx @@ -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 ( + + + + Founders Club + + + 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. + + + + + ); +} diff --git a/components/FAQ.tsx b/components/FAQ.tsx new file mode 100644 index 0000000..b85c884 --- /dev/null +++ b/components/FAQ.tsx @@ -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(false); + + const handleChange = + (panel: string) => (event: React.SyntheticEvent, isExpanded: boolean) => { + setExpanded(isExpanded ? panel : false); + }; + + return ( + + + Frequently asked questions + + + + } + aria-controls="panel1d-content" + id="panel1d-header" + > + + What if I am banned on Stripe? + + + + + You can reach out to our customer support on discord. We will help you figure out a solution tailored to your situation. + + + + + } + aria-controls="panel2d-content" + id="panel2d-header" + > + + What happens if I dont like the art the artist provided? + + + + + 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. + + + + + } + aria-controls="panel3d-content" + id="panel3d-header" + > + + What makes your product stand out from others in the market? + + + + + We provide support for the artists incase of chargebacks and other problems caused by problematic clients. + + + + + } + aria-controls="panel4d-content" + id="panel4d-header" + > + + What countries are supported on the platforms for clients or for artists? + + + + + 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. + + + + + + ); +} diff --git a/components/Footer.tsx b/components/Footer.tsx new file mode 100644 index 0000000..37bf46e --- /dev/null +++ b/components/Footer.tsx @@ -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 ( + + {'Copyright © '} + Request.Box  + {new Date().getFullYear()} + + ); +} + +export default function Footer() { + return ( + + +
+ + Privacy Policy + + +  •  + + + Terms of Service + + +
+ + + + + + + + + + + +
+
+ ); +} diff --git a/components/Hero.tsx b/components/Hero.tsx new file mode 100644 index 0000000..31865fc --- /dev/null +++ b/components/Hero.tsx @@ -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 ( + ({ + width: '100%', + backgroundImage: + theme.palette.mode === 'light' + ? 'linear-gradient(180deg, #CEE5FD, #FFF)' + : 'linear-gradient(#02294F, #090E10)', + backgroundSize: '100% 20%', + backgroundRepeat: 'no-repeat', + })} + > + + + + Artists are  + + theme.palette.mode === 'light' ? 'primary.main' : 'primary.light', + }} + > + protected. + + + + 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. + + + + + + By clicking "Become an artist" you agree to our  + + Terms & Conditions + + . + + + + + ); +} diff --git a/components/Highlights.tsx b/components/Highlights.tsx new file mode 100644 index 0000000..b271cba --- /dev/null +++ b/components/Highlights.tsx @@ -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: , + 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: , + 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: , + 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: , + title: 'Payout Management', + description: + 'Manage information about how you recieve your payments and view statistics about them in a user friendly dashboard', + }, + { + icon: , + title: 'Reliable support', + description: + 'Get support directly from the developers and other staff members in the community discord.', + }, + { + icon: , + title: 'Small Business', + description: + 'Software and its community is developed and maintained by its developer and founder.', + }, +]; + +export default function Highlights() { + return ( + + + + + Highlights + + + 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. + + + + {items.map((item, index) => ( + + + {item.icon} +
+ + {item.title} + + + {item.description} + +
+
+
+ ))} +
+
+
+ ); +} diff --git a/components/Pricing.tsx b/components/Pricing.tsx new file mode 100644 index 0000000..c56ce6b --- /dev/null +++ b/components/Pricing.tsx @@ -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 ( + + + + Pricing + + + Quickly build an effective pricing table for your potential customers with + this layout.
+ It's built with default Material UI components with little + customization. +
+
+ + {tiers.map((tier) => ( + + + + + + {tier.title} + + {tier.title === 'Professional' && ( + } + 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', + }, + }} + /> + )} + + + + ${tier.price} + + +   per month + + + + {tier.description.map((line) => ( + + + + {line} + + + ))} + + + + + + + ))} + +
+ ); +} diff --git a/components/RootSvg.tsx b/components/RootSvg.tsx new file mode 100644 index 0000000..62a1180 --- /dev/null +++ b/components/RootSvg.tsx @@ -0,0 +1,13 @@ +import { styled, Theme } from '@mui/material/styles'; +import { SxProps } from '@mui/system'; + +export type RootSvgProps

= Omit, 'ref'> & { + sx?: SxProps; + ref?: React.Ref; +} & P; + +const Svg = styled('svg')({ + verticalAlign: 'bottom', +}); + +export default Svg; diff --git a/components/SvgMaterialDesign.tsx b/components/SvgMaterialDesign.tsx new file mode 100644 index 0000000..8b7dc36 --- /dev/null +++ b/components/SvgMaterialDesign.tsx @@ -0,0 +1,21 @@ +import * as React from 'react'; +import RootSvg, { RootSvgProps } from './RootSvg'; + +function SvgMaterialDesign(props: RootSvgProps) { + return ( + + + + + + ); +} + +export default SvgMaterialDesign; diff --git a/components/artistDashboardRequest.tsx b/components/artistDashboardRequest.tsx new file mode 100644 index 0000000..a8182ac --- /dev/null +++ b/components/artistDashboardRequest.tsx @@ -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 ? ( + + + + + 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/artistPortfolio.tsx index 836707b..3d5c47e 100644 --- a/components/artistPortfolio.tsx +++ b/components/artistPortfolio.tsx @@ -13,7 +13,7 @@ const ArtistPortfolio = ({artistId}) => { setPortfolioData(data); setLoading(false); } - ////console.log(portfolioData) + (portfolioData) getData(); }, []); return ( diff --git a/components/editableArtistPortfolio.tsx b/components/editableArtistPortfolio.tsx index 9523721..7edb5ff 100644 --- a/components/editableArtistPortfolio.tsx +++ b/components/editableArtistPortfolio.tsx @@ -45,9 +45,8 @@ const EditableArtistPortfolio = ({ artistId }) => { ) : ( - (portfolioData.length > 0 ?(<> - + { sx={{width:"100%"}} startIcon={} > - Add Image + {(portfolioData.length > 0 ? "Upload Another Portfolio Image" : "Upload Your First Portfolio Image")} + + + {portfolioData.map((item) => ( + + ))} + + - - {portfolioData.map((item) => ( - - ))} - - - ) : ( - - - - - )) + ) ) } diff --git a/components/editableArtistPortfolioImage.tsx b/components/editableArtistPortfolioImage.tsx index 4cf69fe..a76cfc6 100644 --- a/components/editableArtistPortfolioImage.tsx +++ b/components/editableArtistPortfolioImage.tsx @@ -8,18 +8,22 @@ import { CircularProgress, ImageListItemBar } from '@mui/material'; import { IconButton } from '@mui/material'; -const EditableArtistPortfolioImage = ({artistId,itemId}) => { +const EditableArtistPortfolioImage = ({artistId,itemId,reload}) => { const [loaded, setLoaded] = useState(false); + const [deleting, setDeleting] = useState(false); const handleImageLoaded = () => { setLoaded(true); }; const deleteButton = () => { + setDeleting(true); fetch('/api/artist/portfolio/'+itemId+"/delete", { method: 'DELETE' - }).then(response => - window.location.reload()); + }).then(response => { + reload().then(data => { + }) + }) } return ( diff --git a/components/layout.tsx b/components/layout.tsx index 5efb898..0ddff72 100644 --- a/components/layout.tsx +++ b/components/layout.tsx @@ -22,7 +22,7 @@ const Layout = ({ user, loading = false, children }: LayoutProps) => { diff --git a/package-lock.json b/package-lock.json index 91d7fe6..45f72b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@fontsource/roboto": "^5.0.8", "@lupus-ai/mui-currency-textfield": "^1.0.3", "@mui/icons-material": "^5.15.6", + "@mui/lab": "^5.0.0-alpha.165", "@mui/material": "^5.15.6", "@mui/x-data-grid": "^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": { "version": "5.15.6", "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.6.tgz", @@ -534,12 +606,12 @@ } }, "node_modules/@mui/private-theming": { - "version": "5.15.6", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.6.tgz", - "integrity": "sha512-ZBX9E6VNUSscUOtU8uU462VvpvBS7eFl5VfxAzTRVQBHflzL+5KtnGrebgf6Nd6cdvxa1o0OomiaxSKoN2XDmg==", + "version": "5.15.9", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.15.9.tgz", + "integrity": "sha512-/aMJlDOxOTAXyp4F2rIukW1O0anodAMCkv1DfBh/z9vaKHY3bd5fFf42wmP+0GRmwMinC5aWPpNfHXOED1fEtg==", "dependencies": { - "@babel/runtime": "^7.23.8", - "@mui/utils": "^5.15.6", + "@babel/runtime": "^7.23.9", + "@mui/utils": "^5.15.9", "prop-types": "^15.8.1" }, "engines": { @@ -560,13 +632,13 @@ } }, "node_modules/@mui/styled-engine": { - "version": "5.15.6", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.6.tgz", - "integrity": "sha512-KAn8P8xP/WigFKMlEYUpU9z2o7jJnv0BG28Qu1dhNQVutsLVIFdRf5Nb+0ijp2qgtcmygQ0FtfRuXv5LYetZTg==", + "version": "5.15.9", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.15.9.tgz", + "integrity": "sha512-NRKtYkL5PZDH7dEmaLEIiipd3mxNnQSO+Yo8rFNBNptY8wzQnQ+VjayTq39qH7Sast5cwHKYFusUrQyD+SS4Og==", "dependencies": { - "@babel/runtime": "^7.23.8", + "@babel/runtime": "^7.23.9", "@emotion/cache": "^11.11.0", - "csstype": "^3.1.2", + "csstype": "^3.1.3", "prop-types": "^15.8.1" }, "engines": { @@ -591,17 +663,17 @@ } }, "node_modules/@mui/system": { - "version": "5.15.6", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.6.tgz", - "integrity": "sha512-J01D//u8IfXvaEHMBQX5aO2l7Q+P15nt96c4NskX7yp5/+UuZP8XCQJhtBtLuj+M2LLyXHYGmCPeblsmmscP2Q==", + "version": "5.15.9", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.15.9.tgz", + "integrity": "sha512-SxkaaZ8jsnIJ77bBXttfG//LUf6nTfOcaOuIgItqfHv60ZCQy/Hu7moaob35kBb+guxVJnoSZ+7vQJrA/E7pKg==", "dependencies": { - "@babel/runtime": "^7.23.8", - "@mui/private-theming": "^5.15.6", - "@mui/styled-engine": "^5.15.6", + "@babel/runtime": "^7.23.9", + "@mui/private-theming": "^5.15.9", + "@mui/styled-engine": "^5.15.9", "@mui/types": "^7.2.13", - "@mui/utils": "^5.15.6", + "@mui/utils": "^5.15.9", "clsx": "^2.1.0", - "csstype": "^3.1.2", + "csstype": "^3.1.3", "prop-types": "^15.8.1" }, "engines": { @@ -643,11 +715,11 @@ } }, "node_modules/@mui/utils": { - "version": "5.15.6", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.6.tgz", - "integrity": "sha512-qfEhf+zfU9aQdbzo1qrSWlbPQhH1nCgeYgwhOVnj9Bn39shJQitEnXpSQpSNag8+uty5Od6PxmlNKPTnPySRKA==", + "version": "5.15.9", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.15.9.tgz", + "integrity": "sha512-yDYfr61bCYUz1QtwvpqYy/3687Z8/nS4zv7lv/ih/6ZFGMl1iolEvxRmR84v2lOYxlds+kq1IVYbXxDKh8Z9sg==", "dependencies": { - "@babel/runtime": "^7.23.8", + "@babel/runtime": "^7.23.9", "@types/prop-types": "^15.7.11", "prop-types": "^15.8.1", "react-is": "^18.2.0" diff --git a/package.json b/package.json index 329b21e..18dae62 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@fontsource/roboto": "^5.0.8", "@lupus-ai/mui-currency-textfield": "^1.0.3", "@mui/icons-material": "^5.15.6", + "@mui/lab": "^5.0.0-alpha.165", "@mui/material": "^5.15.6", "@mui/x-data-grid": "^6.19.4", "@mui/x-date-pickers": "^6.19.4", diff --git a/pages/api/artist/portfolio.tsx b/pages/api/artist/portfolio.tsx index 7454a31..61df741 100644 --- a/pages/api/artist/portfolio.tsx +++ b/pages/api/artist/portfolio.tsx @@ -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 }); - //console.log(response) + (response) if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.message || 'Failed to upload file'); diff --git a/pages/api/discovery/artist/[sellerId]/portfolio.tsx b/pages/api/discovery/artist/[sellerId]/portfolio.tsx index 554ea79..de058e0 100644 --- a/pages/api/discovery/artist/[sellerId]/portfolio.tsx +++ b/pages/api/discovery/artist/[sellerId]/portfolio.tsx @@ -1,14 +1,13 @@ export default async function handler(req, res ): Promise { const { sellerId } = req.query; var url = process.env.NEXT_PUBLIC_API_URL+`/api/Discovery/Sellers/${sellerId}/Portfolio`; - ////console.log(url) + (url) const response = await fetch(url); - console.log(response) if (!response.ok) { throw new Error('Failed to fetch seller portfolio'); } var result = await response.json(); - ////console.log(result) + (result) res.status(200).json(result); } diff --git a/pages/artistDashboard.tsx b/pages/artistDashboard.tsx index 89efe2e..ccbb6be 100644 --- a/pages/artistDashboard.tsx +++ b/pages/artistDashboard.tsx @@ -4,15 +4,19 @@ import AppBar from '@mui/material/AppBar'; import Tabs from '@mui/material/Tabs'; import Tab from '@mui/material/Tab'; import Layout from "../components/layout"; -import { Grid, Button, Typography, TextField, Box, CircularProgress } from "@mui/material"; -import { useState, useEffect } from "react"; +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"; @@ -20,21 +24,16 @@ import EditableArtistPortfolio from "../components/editableArtistPortfolio"; const SellerDashoard = (ctx) => { const { user, isLoading } = useUser(); - const [sellerRequestData, setSellerRequestData] = useState([]); 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 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 onboardCheckResponse = await onboardCheckRequest.json(); setIsOnboarded(onboardCheckResponse["onboarded"]); @@ -45,6 +44,8 @@ const SellerDashoard = (ctx) => { setLoading(false); // Once data is fetched, set loading to false } + + const handleChange = (event: React.SyntheticEvent, newValue: number) => { setTabValue(newValue); }; @@ -92,11 +93,57 @@ const SellerDashoard = (ctx) => { getData(); }, []); const theme = useTheme(); - const columns: GridColDef[] = [ { field: 'requestor', headerName: 'User', width: 150 }, { 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(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 ( + <> + + + + + + + ) + } + } ]; const rows = [ { 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 ( <> @@ -154,8 +171,7 @@ const SellerDashoard = (ctx) => { ) : ( - - + {(Object.keys(sellerData).length > 0 ? ( <> @@ -172,95 +188,7 @@ const SellerDashoard = (ctx) => { - {(Object.keys(sellerRequestData).length > 0 ? ( - <> - - - - - Request Status - - {(sellerRequestData["accepted"] ? ( - Accepted - ) : ( - Pending - ))} - Request submitted on {formattedTime ?? ''} - - - - - - - - {(sellerRequestData["accepted"] ? ( - <> - - {(isOnboarded ? (<> - - - - ) : ( - <> - - - - ))} - - - - - - - - - - - - - - - - - - - - Item Three - - - - - ) : ( -<> ))} - - - ) : ( - <> - - {(Object.keys(sellerRequestData).length==0 || sellerRequestData["accepted"]==false ? (<>):(<>))} - - - ))} + ) : ( diff --git a/pages/index.tsx b/pages/index.tsx index 2d8aeb0..266b865 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -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 Layout from "../components/layout"; -import { Typography, Box, CircularProgress } from '@mui/material'; -import Artist from "../components/artist"; -import { useEffect, useState } from "react"; +const defaultTheme = createTheme({}); -const Home = () => { - const [sellersData, setSellersData] = useState([]); - const [loading, setLoading] = useState(true); // State for loading indicator - useEffect(() => { - const getData = async () => { - const response = await fetch('/api/discovery/artists'); - const data = await response.json(); - setSellersData(data); - setLoading(false); - } - getData(); - }, []); - const { user, isLoading } = useUser(); +interface ToggleCustomThemeProps { + showCustomTheme: Boolean; + toggleCustomTheme: () => void; +} + +function ToggleCustomTheme({ + showCustomTheme, + toggleCustomTheme, +}: ToggleCustomThemeProps) { return ( - - {loading ? ( // Render loading indicator if loading is true - - - Loading - - - - - ) : ( - <> - {sellersData.map((item) => ( - - ))} - - )} - + + + + + Custom theme + + + + Material Design + + + ); -}; +} -// fast/cached SSR page -export default Home; \ No newline at end of file +export default function LandingPage() { + const [showCustomTheme, setShowCustomTheme] = React.useState(true); + + const { user, isLoading } = useUser(); + + const toggleCustomTheme = () => { + setShowCustomTheme((prev) => !prev); + }; + + return ( + + + + + + + + + + +