This commit is contained in:
Damien Ostler 2024-02-14 23:48:46 -05:00
parent 52c111ab36
commit ed48b67e3c
13 changed files with 234 additions and 85 deletions

View File

@ -40,13 +40,13 @@ const Artist = ({user, artistId}) => {
<Grid item xs={6} md={8}>
<Item>
<Typography variant="h5" component="h2">
{sellerData.name}
{sellerData["name"]}
</Typography>
<Typography color="primary">
{sellerData.averageRating ? `${sellerData.averageRating} Stars (${sellerData.reviewCount} Reviews)` : "No Reviews"}
{sellerData["averageRating"] ? `${sellerData["averageRating"]} Stars (${sellerData["reviewCount"]} Reviews)` : "No Reviews"}
</Typography>
<Typography variant="body2" component="p">
{sellerData.biography}
{sellerData["biography"]}
</Typography>
</Item>

View File

@ -13,14 +13,14 @@ const ArtistPortfolio = ({artistId}) => {
setPortfolioData(data);
setLoading(false);
}
console.log(portfolioData)
//console.log(portfolioData)
getData();
}, []);
return (
(loading) ? (
<Box sx={{textAlign:"center", paddingTop:20}}>
<Typography variant="h4" sx={{textAlign:"center"}}>
Loading...
Loading
</Typography>
<CircularProgress sx={{paddingTop:5}} />
</Box>

View File

@ -0,0 +1,80 @@
import * as React from 'react';
import { ImageList, Box, Button, CircularProgress } from '@mui/material';
import { useEffect, useState } from "react";
import EditableArtistPortfolioImage from './editableArtistPortfolioImage';
import FileOpenIcon from '@mui/icons-material/FileOpen';
import { Grid } from '@mui/material';
const EditableArtistPortfolio = ({ artistId }) => {
const [portfolioData, setPortfolioData] = useState([]);
const [loading, setLoading] = useState(true); // State for loading indicator
useEffect(() => {
getData();
}, []);
const getData = async () => {
const response = await fetch('/api/discovery/artist/' + artistId + '/portfolio');
const data = await response.json();
setPortfolioData(data);
setLoading(false);
}
function handlePortfolioUploadImageChange(event) {
const file = event.target.files[0];
const formData = new FormData();
formData.append('file', file);
fetch('/api/artist/portfolio', {
method: 'POST',
body: formData // Don't set Content-Type, FormData will handle it
})
.then(response => response.json())
.then(data => {
getData();
})
.catch(error => {
console.error('Error uploading file:', error);
// Handle error appropriately
});
}
return (
(loading) ? (
<Box sx={{ textAlign: "center", paddingTop: 20 }}>
<CircularProgress sx={{ paddingTop: 5 }} />
</Box>
) :
(
<Grid container spacing={2} sx={{ padding: 4 }}>
<Grid item xs={12} sm={12} 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"
startIcon={<FileOpenIcon />}
>
Add Image
</Button>
</label>
</Grid>
<Grid item xs={12} sm={12} sx={{ textAlign: "center" }}>
<ImageList cols={2} rowHeight={200} sx={{ maxHeight: 400 }}>
{portfolioData.map((item) => (
<EditableArtistPortfolioImage artistId={artistId} itemId={item.id} />
))}
</ImageList>
</Grid>
</Grid>
)
)
}
export default EditableArtistPortfolio

View File

@ -0,0 +1,28 @@
import * as React from 'react';
import ImageList from '@mui/material/ImageList';
import ImageListItem from '@mui/material/ImageListItem';
import { useEffect, useState } from "react";
import { CircularProgress } from '@mui/material';
import { IconButton } from '@mui/material';
const EditableArtistPortfolioImage = ({artistId,itemId}) => {
const [loaded, setLoaded] = useState(false);
const handleImageLoaded = () => {
setLoaded(true);
};
return (
<ImageListItem key={itemId }>
<img
srcSet={process.env.NEXT_PUBLIC_API_URL+`/api/Discovery/Sellers/${artistId}/Portfolio/${itemId}`}
src={process.env.NEXT_PUBLIC_API_URL+`/api/Discovery/Sellers/${artistId}/Portfolio/${itemId}`}
alt={itemId}
loading="lazy"
style={{ filter: loaded ? 'blur(0)' : 'blur(10px)', backgroundColor:'grey' }}
onLoad={handleImageLoaded}
/>
</ImageListItem>)
}
export default EditableArtistPortfolioImage

49
package-lock.json generated
View File

@ -16,6 +16,7 @@
"@mui/x-date-pickers": "^6.19.4",
"@novu/notification-center": "^0.22.0",
"dayjs": "^1.11.10",
"formidable": "^3.5.1",
"next": "latest",
"openapi-typescript-fetch": "^1.1.3",
"react": "^18.2.0",
@ -1259,6 +1260,11 @@
"node": ">=10"
}
},
"node_modules/asap": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@ -1478,6 +1484,15 @@
"node": ">= 0.6"
}
},
"node_modules/dezalgo": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
"integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
"dependencies": {
"asap": "^2.0.0",
"wrappy": "1"
}
},
"node_modules/dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
@ -1563,6 +1578,19 @@
"node": ">= 6"
}
},
"node_modules/formidable": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.1.tgz",
"integrity": "sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==",
"dependencies": {
"dezalgo": "^1.0.4",
"hexoid": "^1.0.0",
"once": "^1.4.0"
},
"funding": {
"url": "https://ko-fi.com/tunnckoCore/commissions"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
@ -1595,6 +1623,14 @@
"node": ">= 0.4"
}
},
"node_modules/hexoid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz",
"integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==",
"engines": {
"node": ">=8"
}
},
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
@ -1846,6 +1882,14 @@
"node": "^10.13.0 || >=12.0.0"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/openapi-typescript-fetch": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/openapi-typescript-fetch/-/openapi-typescript-fetch-1.1.3.tgz",
@ -2326,6 +2370,11 @@
"resolved": "https://registry.npmjs.org/webfontloader/-/webfontloader-1.6.28.tgz",
"integrity": "sha512-Egb0oFEga6f+nSgasH3E0M405Pzn6y3/9tOVanv/DLfa1YBIgcv90L18YyWnvXkRbIM17v5Kv6IT2N6g1x5tvQ=="
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/ws": {
"version": "8.11.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",

View File

@ -17,6 +17,7 @@
"@mui/x-date-pickers": "^6.19.4",
"@novu/notification-center": "^0.22.0",
"dayjs": "^1.11.10",
"formidable": "^3.5.1",
"next": "latest",
"openapi-typescript-fetch": "^1.1.3",
"react": "^18.2.0",

View File

@ -0,0 +1,49 @@
import { getAccessToken, withApiAuthRequired } from '@auth0/nextjs-auth0';
import { IncomingForm } from 'formidable'
export const config = {
api: {
bodyParser: false,
},
};
export default withApiAuthRequired(async function handler(req, res) {
const { accessToken } = await getAccessToken(req, res);
const form = new IncomingForm();
form.parse(req, async (err, fields, files) => {
if (err) {
console.error('Error parsing form:', err);
res.status(500).json({ error: 'Error parsing form' });
return;
}
const file = files["file"]; // Assuming your file input field name is 'file'
console.log(file)
const formData = new FormData();
formData.append('file', file); // Append the file to FormData
console.log(formData)
try {
const response = await fetch(process.env.NEXT_PUBLIC_API_URL + '/api/SellerProfile/Portfolio', {
method: 'POST',
headers: {
"Authorization": `Bearer ${accessToken}`
},
body: formData // Don't set Content-Type, FormData will handle it
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Failed to upload file');
}
const responseData = await response.json();
res.status(200).json(responseData);
} catch (error) {
console.error('Error uploading file:', error);
res.status(500).json({ error: 'Error uploading file' });
}
});
});

View File

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

View File

@ -30,10 +30,11 @@ const SellerProfile = () => {
{loading ? ( // Render loading indicator if loading is true
<Box sx={{textAlign:"center", paddingTop:20}}>
<Typography variant="h4" sx={{textAlign:"center"}}>
Loading...
Loading
</Typography>
<CircularProgress sx={{paddingTop:5}} />
</Box>
<Box sx={{ paddingTop: 5 }} />
<CircularProgress />
</Box>
) : (
<Grid container spacing={2} sx={{padding:4}}>
<Grid container sx={{textAlign:"center"}}>
@ -44,7 +45,7 @@ const SellerProfile = () => {
</Grid>
<Grid item xs={12} sm={8} sx={{textAlign:"center"}}>
<Typography variant="h4">
{sellerData.name}
{sellerData["name"]}
</Typography>
</Grid>
<Grid item xs={12} sm={2} sx={{textAlign:"center"}}>
@ -57,7 +58,7 @@ const SellerProfile = () => {
Biography
</Typography>
<Typography sx={{paddingTop:2, textAlign:"center"}}>
{sellerData.biography}
{sellerData["biography"]}
</Typography>
</CardContent>
</Card>

View File

@ -40,9 +40,10 @@ const SellerProfile = () => {
{loading ? ( // Render loading indicator if loading is true
<Box sx={{textAlign:"center", paddingTop:20}}>
<Typography variant="h4" sx={{textAlign:"center"}}>
Loading...
Loading
</Typography>
<CircularProgress sx={{paddingTop:5}} />
<Box sx={{ paddingTop: 5 }} />
<CircularProgress />
</Box>
) : (
<Grid container spacing={2} sx={{padding:4}}>
@ -65,7 +66,7 @@ const SellerProfile = () => {
<>
<Grid item xs={12} sm={12} sx={{textAlign:"center"}} >
<TextField fullWidth disabled id="fo" label="Artist" variant="outlined" value={sellerData.name}/>
<TextField fullWidth disabled id="fo" label="Artist" variant="outlined" value={sellerData["name"]}/>
<Box sx={{padding:2}} />
<TextField id="outlined-multiline-static" label="Request Details" fullWidth multiline rows={4} defaultValue="" placeholder="Put the details of your request. Links to reference images. Descriptions of what you want. Things like that."/>
<Box sx={{padding:2}} />

View File

@ -12,6 +12,7 @@ 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 EditableArtistPortfolio from "../components/editableArtistPortfolio";
@ -146,9 +147,10 @@ const SellerDashoard = (ctx) => {
{loading ? ( // Render loading indicator if loading is true
<Box sx={{ textAlign: "center", paddingTop: 20 }}>
<Typography variant="h4" sx={{ textAlign: "center" }}>
Loading...
Loading
</Typography>
<CircularProgress sx={{ paddingTop: 5 }} />
<Box sx={{ paddingTop: 5 }} />
<CircularProgress />
</Box>
) : (
<Layout user={user} loading={isLoading}>
@ -240,7 +242,7 @@ const SellerDashoard = (ctx) => {
/>
</TabPanel>
<TabPanel value={tabValue} index={1} dir={theme.direction}>
Item Two
<EditableArtistPortfolio artistId={sellerData["id"]}></EditableArtistPortfolio>
</TabPanel>
<TabPanel value={tabValue} index={2} dir={theme.direction}>
Item Three
@ -262,70 +264,7 @@ const SellerDashoard = (ctx) => {
</>
) : (
<>
<Grid item container sx={{ textAlign: "center" }}>
<Grid item xs={12} sm={10} sx={{ textAlign: "center" }}>
</Grid>
<Grid item xs={12} sm={2} sx={{ textAlign: "center" }}>
<Button color="secondary" variant="contained" href="../">
Save
</Button>
</Grid>
</Grid>
<Grid item container xs={12} sm={12}>
<Grid item xs={12} sm={12}>
<TextField variant="filled" fullWidth label="Artist Name" />
<Box sx={{ padding: 1 }} />
<TextField variant="outlined" fullWidth multiline rows={4} label="Biography" />
<Box sx={{ padding: 1 }} />
</Grid>
<Grid item xs={12} sm={12} sx={{ textAlign: "center" }}>
<Button sx={{ width: "50%" }} color="success" variant="contained">Payout Portal</Button>
</Grid>
</Grid>
<Grid item container xs={12} sm={12}>
<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}>
Item Two
</TabPanel>
<TabPanel value={tabValue} index={2} dir={theme.direction}>
Item Three
</TabPanel>
</SwipeableViews>
</Grid>
</>
<></>
))}
<Grid item container xs={12} sm={12}>
</Grid>

View File

@ -22,9 +22,10 @@ const Home = () => {
{loading ? ( // Render loading indicator if loading is true
<Box sx={{textAlign:"center", paddingTop:20}}>
<Typography variant="h4" sx={{textAlign:"center"}}>
Loading...
Loading
</Typography>
<CircularProgress sx={{paddingTop:5}} />
<Box sx={{ paddingTop: 5 }} />
<CircularProgress />
</Box>
) : (
<>

View File

@ -24,7 +24,7 @@ const ProfileCard = ({ user }: ProfileCardProps) => {
const Profile = ({ user, isLoading }) => {
return (
<Layout user={user} loading={isLoading}>
{isLoading ? <>Loading...</> : <ProfileCard user={user} />}
{isLoading ? <>Loading</> : <ProfileCard user={user} />}
</Layout>
);
};