mirror of
				https://github.com/D4M13N-D3V/comissions-app-ui.git
				synced 2025-10-31 01:25:22 +00:00 
			
		
		
		
	feat: added pages for viewing artist access requests, users, and artists in the admin menus
This commit is contained in:
		
							parent
							
								
									23ea8eed79
								
							
						
					
					
						commit
						2a405067d8
					
				| @ -10,8 +10,7 @@ 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, Logout, OpenInNew } from '@mui/icons-material'; | ||||
| import { Logout, OpenInNew } from '@mui/icons-material'; | ||||
| 
 | ||||
| const logoStyle = { | ||||
|   width: '140px', | ||||
|  | ||||
| @ -4,10 +4,6 @@ import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; | ||||
| import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; | ||||
| import { useRouter } from 'next/router'; | ||||
| import { Rating } from '@mui/material'; | ||||
| import dayjs from 'dayjs'; | ||||
| 
 | ||||
| import CurrencyTextField from '@lupus-ai/mui-currency-textfield'; | ||||
| import { DateField } from '@mui/x-date-pickers'; | ||||
| 
 | ||||
| export default function Reviews({artistId}) { | ||||
|     const router = useRouter(); | ||||
| @ -36,9 +32,13 @@ export default function Reviews({artistId}) { | ||||
|       } | ||||
|     }); | ||||
|     const data = await response.json(); | ||||
|     setReviewData(data); | ||||
|     // Assuming your API returns an array under a key like 'reviews'
 | ||||
|     // Adjust this according to your actual API response structure
 | ||||
|     const rows = data.reviews || []; // If 'reviews' doesn't exist, default to an empty array
 | ||||
|     setReviewData(rows); | ||||
|     setIsLoading(false); | ||||
|   } | ||||
|    | ||||
|   const getReviewsCount = async () => { | ||||
|     const response = await fetch('/api/discovery/artist/'+artistId+'/reviewscount', { | ||||
|         method: 'GET', | ||||
|  | ||||
							
								
								
									
										0
									
								
								components/test.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								components/test.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -3,7 +3,7 @@ import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-a | ||||
| export default withApiAuthRequired(async function handler(req, res) { | ||||
|   const { accessToken } = await getAccessToken(req, res); | ||||
|   const { artistId } = req.query; | ||||
|   const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminArtists/'+userId, { | ||||
|   const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminArtists/'+artistId, { | ||||
|     headers: { | ||||
|       "Authorization": `Bearer ${accessToken}` | ||||
|     } | ||||
|  | ||||
| @ -9,10 +9,7 @@ export default withApiAuthRequired(async function handler(req, res) { | ||||
|     }, | ||||
|     method: req.method | ||||
|   }); | ||||
|   if(response.ok==false){ | ||||
|     res.status(200).json({}) | ||||
|     return; | ||||
|   } | ||||
|   console.log(response) | ||||
|   let result = await response.json(); | ||||
|   res.status(200).json(result); | ||||
| }); | ||||
|  | ||||
							
								
								
									
										16
									
								
								pages/api/artist/artistAccessRequest.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								pages/api/artist/artistAccessRequest.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-auth0'; | ||||
| 
 | ||||
| export default withApiAuthRequired(async function products(req, res) { | ||||
|   const { accessToken } = await getAccessToken(req, res); | ||||
|   const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/Artist', { | ||||
|     headers: { | ||||
|       "Authorization": `Bearer ${accessToken}`, | ||||
|       'Content-Type': 'application/json' | ||||
|     }, | ||||
|     method: 'POST', | ||||
|     body: req.body | ||||
|   }); | ||||
|   let result = await response.json(); | ||||
|   res.status(200).json(result); | ||||
| }); | ||||
| 
 | ||||
| @ -65,7 +65,7 @@ export default function AdminArtists() { | ||||
|                 } | ||||
|             }}, | ||||
|             { field: 'actions', headerName: '', flex: 0.05, sortable: false, filterable: false, renderCell: (params) => { | ||||
|                 return <Tooltip title="View more information about this user."><IconButton color="info" onClick={() => router.push("/dashboard/admin/users/"+params.row.id)}><OpenInNew /></IconButton></Tooltip> | ||||
|                 return <Tooltip title="View more information about this user."><IconButton color="info" onClick={() => router.push("/dashboard/admin/artists/"+params.row.id)}><OpenInNew /></IconButton></Tooltip> | ||||
|             }} | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
| @ -2,13 +2,23 @@ import * as React from 'react'; | ||||
| import { useState, useEffect } from 'react'; | ||||
| import { useRouter } from 'next/router'; | ||||
| import { withPageAuthRequired } from '@auth0/nextjs-auth0/client' | ||||
| import { Alert, Card, CardContent, Grid, IconButton, TextField, Typography } from '@mui/material'; | ||||
| import { ArrowBack, ArrowLeft, Block, Close } from '@mui/icons-material'; | ||||
| import Button from '@mui/material/Button'; | ||||
| import { OpenInNew } from 'mdi-material-ui'; | ||||
| import Tooltip from '@mui/material/Tooltip'; | ||||
| 
 | ||||
| const AdminArtist = () => { | ||||
|     const router = useRouter(); | ||||
| 
 | ||||
| 
 | ||||
|     const [artist, setArtist] = useState(null); | ||||
| 
 | ||||
|     const getData = async () => { | ||||
|         if(router.query.artistId!=null){ | ||||
|              | ||||
|             const response = await fetch("/api/admin/artists/"+router.query.artistId); | ||||
|             const data = await response.json(); | ||||
|             setArtist(data); | ||||
|         } | ||||
|     } | ||||
|    | ||||
| @ -17,12 +27,78 @@ const AdminArtist = () => { | ||||
|         getData() | ||||
|     }, [router.query.artistId]); | ||||
| 
 | ||||
|     return (<> | ||||
|     return ( | ||||
|         <> | ||||
|         <Card> | ||||
|             <CardContent> | ||||
|                 <Grid container spacing={3}> | ||||
|                     <Grid item xs={6}> | ||||
|                         <Typography variant="h5">Artist Information</Typography> | ||||
|                     </Grid> | ||||
|                     <Grid item xs={6} sx={{textAlign:"right"}}> | ||||
|                         <Tooltip title="Ban this artist."> | ||||
|                             <IconButton color="error"> | ||||
|                                 <Block/> | ||||
|                             </IconButton> | ||||
|                         </Tooltip> | ||||
|                         <Tooltip title="Suspend this artist."> | ||||
|                             <IconButton color="warning"> | ||||
|                                 <Close/> | ||||
|                             </IconButton> | ||||
|                         </Tooltip> | ||||
|                         <Tooltip title="Go back a page."> | ||||
|                             <IconButton onClick={() => router.push("/dashboard/admin/artists")} color="primary"> | ||||
|                                 <ArrowBack/> | ||||
|                             </IconButton> | ||||
|                         </Tooltip> | ||||
|                     </Grid> | ||||
|                     <Grid item xs={12}  md={6}> | ||||
|                         <Grid container spacing={3}> | ||||
|                             <Grid item xs={12} md={5}> | ||||
|                                 <Grid container spacing={3}> | ||||
|                                     <Grid item xs={12}> | ||||
|                                         Display Name: {artist?.user?.displayName} | ||||
|                                     </Grid> | ||||
|                                     <Grid item xs={12}> | ||||
|                                         Email: {artist?.user?.email} | ||||
|                                     </Grid> | ||||
|                                     <Grid item xs={12}> | ||||
|                                         <Button variant="contained" color="primary" fullWidth>Save Changes</Button> | ||||
|                                     </Grid> | ||||
|                                 </Grid> | ||||
|                             </Grid> | ||||
|                             <Grid item xs={12} md={7}> | ||||
|                                 <TextField size="small" label="Admin Notes" multiline rows={4} fullWidth variant="outlined" value={artist?.userId} /> | ||||
|                             </Grid> | ||||
|                             <Grid item xs={12}> | ||||
|                                 <Alert severity={artist?.numberOfBans > 0 ? "error" : "success"}>{artist?.numberOfBans > 0 ? "This user has been banned "+artist?.numberOfBans+" times." : "This user has not been banned before."}</Alert> | ||||
|                             </Grid> | ||||
|                             <Grid item xs={12}> | ||||
|                                 <Alert severity={artist?.numberOfSuspensions > 0 ? "error" : "success"}>{artist?.numberOfBans > 0 ? "This user has been suspended "+artist?.numberOfSuspensions+" times." : "This user has not been suspended before."}</Alert> | ||||
|                             </Grid> | ||||
|                         </Grid> | ||||
|                     </Grid> | ||||
|                     <Grid item xs={12} md={6}> | ||||
|                         <Grid container spacing={3}> | ||||
|                             <Grid item xs={12}> | ||||
|                                 <Alert severity="success">This artist has made ${artist?.amountMade}, and we have made ${artist?.feesCollected} in fees.</Alert> | ||||
|                             </Grid> | ||||
|                             <Grid item xs={12}> | ||||
|                                 <Alert severity={artist?.numberOfRequests > 0 ? "success" : "warning"}>This artist has accepted {artist?.numberOfRequests} requests.</Alert> | ||||
|                             </Grid> | ||||
|                             <Grid item xs={12}> | ||||
|                                 <Alert severity={artist?.numberOfCompleted > 0 ? "success" : "warning"}>This artist has completed {artist?.numberOfCompleted} requests.</Alert> | ||||
|                             </Grid> | ||||
|                         </Grid> | ||||
|                     </Grid> | ||||
|                 </Grid> | ||||
|             </CardContent> | ||||
|         </Card> | ||||
|         </> | ||||
|   ); | ||||
| }; | ||||
| 
 | ||||
| // Protected route, checking user authentication client-side.(CSR)
 | ||||
| export default withPageAuthRequired(ArtistRequestDetails); | ||||
| export default withPageAuthRequired(AdminArtist); | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -2,22 +2,110 @@ import * as React from 'react'; | ||||
| import { useState, useEffect } from 'react'; | ||||
| import { useRouter } from 'next/router'; | ||||
| import { withPageAuthRequired } from '@auth0/nextjs-auth0/client' | ||||
| import { Alert, Card, CardContent, Grid, IconButton, TextField, Typography } from '@mui/material'; | ||||
| import Button from '@mui/material/Button'; | ||||
| import { OpenInNew } from 'mdi-material-ui'; | ||||
| import Tooltip from '@mui/material/Tooltip'; | ||||
| import { ArrowBack } from '@mui/icons-material'; | ||||
| 
 | ||||
| 
 | ||||
| const AdminRequest = () => { | ||||
|     const router = useRouter(); | ||||
| 
 | ||||
|     const [request, setRequest] = useState(null); | ||||
| 
 | ||||
|      | ||||
|     const getData = async () => { | ||||
|         if(router.query.artistId!=null){ | ||||
|              | ||||
|         if(router.query.requestId!=null){ | ||||
|             const response = await fetch("/api/admin/requests/"+router.query.requestId); | ||||
|             const data = await response.json(); | ||||
|             setRequest(data); | ||||
|         } | ||||
|     } | ||||
|    | ||||
|     const handleAccept = async () => { | ||||
|         var response = await fetch("/api/admin/requests/"+router.query.requestId, {method:"PUT"}) | ||||
|         if(response.ok){ | ||||
|             var data = await response.json(); | ||||
|             router.reload(); | ||||
|         } | ||||
|         else{ | ||||
|             alert("Failed to accept request.") | ||||
|         } | ||||
|     } | ||||
|     const handleDeny = async () => { | ||||
|         var response = await fetch("/api/admin/requests/"+router.query.requestId, {method:"DELETE"}) | ||||
|         if(response.ok){ | ||||
|             var data = await response.json(); | ||||
|             router.reload(); | ||||
|         } | ||||
|         else{ | ||||
|             alert("Failed to deny request.") | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     useEffect(() => { | ||||
|         getData() | ||||
|     }, [router.query.artistId]); | ||||
|     }, [router.query.requestId]); | ||||
| 
 | ||||
|     return (<> | ||||
|     let formattedTime = "" | ||||
|     const date = new Date(request?.requestDate);   | ||||
|     formattedTime = date.toLocaleTimeString('en-US', { month: 'long', day: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }); // Example format
 | ||||
|     return ( | ||||
|     <> | ||||
|     <Card> | ||||
|         <CardContent> | ||||
|             <Grid container> | ||||
|                 <Grid item xs={6}> | ||||
|                     <Typography variant="h5">{router.query.requestId} - Artist Access Request</Typography> | ||||
|                 </Grid> | ||||
|                     <Grid item xs={6} sx={{textAlign:"right"}}> | ||||
|                         <Tooltip title="Go back a page."> | ||||
|                             <IconButton onClick={() => router.push("/dashboard/admin/requests")} color="primary"> | ||||
|                                 <ArrowBack/> | ||||
|                             </IconButton> | ||||
|                         </Tooltip> | ||||
|                     </Grid> | ||||
|                 <Grid item xs={6}> | ||||
|                     <Grid container spacing={3}> | ||||
|                         <Grid item xs={12}> | ||||
|                             <Alert severity="info">Submitted on {formattedTime}</Alert> | ||||
|                         </Grid> | ||||
|                         {request?.accepted ? ( | ||||
|                             <Grid item xs={12}> | ||||
|                                 <Alert severity="success">This artist access request has been accepted.</Alert> | ||||
|                             </Grid> | ||||
|                         ):( | ||||
|                             <Grid item xs={12}> | ||||
|                                 <Alert severity="warning">Pending review from platform administrator.</Alert> | ||||
|                             </Grid> | ||||
|                         )} | ||||
|                         <Grid item xs={12}> | ||||
|                             <TextField | ||||
|                                 id="outlined-multiline-static" | ||||
|                                 label="Message" | ||||
|                                 multiline | ||||
|                                 rows={4} | ||||
|                                 fullWidth | ||||
|                                 value={request?.message} | ||||
|                                 disabled> | ||||
|                                     {request?.message} | ||||
|                                 </TextField> | ||||
|                         </Grid> | ||||
|                         <Grid item xs={12} md={6}> | ||||
|                             <Button fullWidth disabled={request?.accepted} variant="contained" onClick={handleAccept} color="primary">Accept</Button> | ||||
|                         </Grid> | ||||
|                         <Grid item xs={12} md={6}> | ||||
|                             <Button fullWidth disabled={request?.accepted} variant="contained" onClick={handleDeny} color="secondary">Reject</Button> | ||||
|                         </Grid> | ||||
|                     </Grid> | ||||
|                 </Grid> | ||||
|                 <Grid item xs={6}> | ||||
| 
 | ||||
|                 </Grid> | ||||
|             </Grid> | ||||
|         </CardContent> | ||||
|     </Card> | ||||
|     </> | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| @ -45,8 +45,8 @@ export default function AdminUsers() { | ||||
|             { field: 'id', headerName: 'User ID', flex: 0.2, sortable: false, filterable: false}, | ||||
|             { field: 'displayName', headerName: 'Display Name', flex: 0.15, sortable: false, filterable: false}, | ||||
|             { field: 'email', headerName: 'Email', flex: 0.2, sortable: false, filterable: false}, | ||||
|             { field: "requestCount", headerName: "# of Requests", flex: 0.1, sortable: false, filterable: false}, | ||||
|             { field: "reviewCount", headerName: "# of Reviews", flex: 0.1, sortable: false, filterable: false}, | ||||
|             { field: "numberOfRequests", headerName: "# of Requests", flex: 0.1, sortable: false, filterable: false}, | ||||
|             { field: "numberOfReviews", headerName: "# of Reviews", flex: 0.1, sortable: false, filterable: false}, | ||||
|             { field: "amountSpent", headerName: "Amount Spent", flex: 0.1, sortable: false, filterable: false}, | ||||
|             { field: 'status', headerName: 'Status', flex: 0.1, sortable: false, filterable: false, renderCell: (params) =>{ | ||||
|                 if(params.row.banned){ | ||||
|  | ||||
| @ -2,22 +2,98 @@ import * as React from 'react'; | ||||
| import { useState, useEffect } from 'react'; | ||||
| import { useRouter } from 'next/router'; | ||||
| import { withPageAuthRequired } from '@auth0/nextjs-auth0/client' | ||||
| import { Alert, Card, CardContent, Grid, IconButton, TextField, Typography } from '@mui/material'; | ||||
| import { ArrowBack, ArrowLeft, Block, Close } from '@mui/icons-material'; | ||||
| import Button from '@mui/material/Button'; | ||||
| import { OpenInNew } from 'mdi-material-ui'; | ||||
| import Tooltip from '@mui/material/Tooltip'; | ||||
| 
 | ||||
| const AdminUser = () => { | ||||
|     const router = useRouter(); | ||||
| 
 | ||||
|     const getData = async () => { | ||||
|         if(router.query.artistId!=null){ | ||||
| 
 | ||||
|     const [user, setUser] = useState(null); | ||||
| 
 | ||||
|     const getData = async () => { | ||||
|         if(router.query.userId!=null){ | ||||
|             const response = await fetch("/api/admin/users/"+router.query.userId); | ||||
|             const data = await response.json(); | ||||
|             setUser(data); | ||||
|         } | ||||
|     } | ||||
|    | ||||
| 
 | ||||
|     useEffect(() => { | ||||
|         getData() | ||||
|     }, [router.query.artistId]); | ||||
|     }, [router.query.userId]); | ||||
| 
 | ||||
|     return (<> | ||||
|     return ( | ||||
|         <> | ||||
|         <Card> | ||||
|             <CardContent> | ||||
|                 <Grid container spacing={3}> | ||||
|                     <Grid item xs={6}> | ||||
|                         <Typography variant="h5">User Information</Typography> | ||||
|                     </Grid> | ||||
|                     <Grid item xs={6} sx={{textAlign:"right"}}> | ||||
|                         <Tooltip title="Ban this user."> | ||||
|                             <IconButton color="error"> | ||||
|                                 <Block/> | ||||
|                             </IconButton> | ||||
|                         </Tooltip> | ||||
|                         <Tooltip title="Suspend this user."> | ||||
|                             <IconButton color="warning"> | ||||
|                                 <Close/> | ||||
|                             </IconButton> | ||||
|                         </Tooltip> | ||||
|                         <Tooltip title="Go back a page."> | ||||
|                             <IconButton onClick={() => router.push("/dashboard/admin/users")} color="primary"> | ||||
|                                 <ArrowBack/> | ||||
|                             </IconButton> | ||||
|                         </Tooltip> | ||||
|                     </Grid> | ||||
|                     <Grid item xs={12}  md={6}> | ||||
|                         <Grid container spacing={3}> | ||||
|                             <Grid item xs={12} md={5}> | ||||
|                                 <Grid container spacing={3}> | ||||
|                                     <Grid item xs={12}> | ||||
|                                         Display Name: {user?.displayName} | ||||
|                                     </Grid> | ||||
|                                     <Grid item xs={12}> | ||||
|                                         Email: {user?.email} | ||||
|                                     </Grid> | ||||
|                                     <Grid item xs={12}> | ||||
|                                         <Button variant="contained" color="primary" fullWidth>Save Changes</Button> | ||||
|                                     </Grid> | ||||
|                                 </Grid> | ||||
|                             </Grid> | ||||
|                             <Grid item xs={12} md={7}> | ||||
|                                 <TextField size="small" label="Admin Notes" multiline rows={4} fullWidth variant="outlined" value={user?.userId} /> | ||||
|                             </Grid> | ||||
|                             <Grid item xs={12}> | ||||
|                                 <Alert severity={user?.numberOfBans > 0 ? "error" : "success"}>{user?.numberOfBans > 0 ? "This user has been banned "+user?.numberOfBans+" times." : "This user has not been banned before."}</Alert> | ||||
|                             </Grid> | ||||
|                             <Grid item xs={12}> | ||||
|                                 <Alert severity={user?.numberOfSuspensions > 0 ? "error" : "success"}>{user?.numberOfBans > 0 ? "This user has been suspended "+user?.numberOfSuspensions+" times." : "This user has not been suspended before."}</Alert> | ||||
|                             </Grid> | ||||
|                         </Grid> | ||||
|                     </Grid> | ||||
|                     <Grid item xs={12} md={6}> | ||||
|                         <Grid container spacing={3}> | ||||
|                             <Grid item xs={12}> | ||||
|                                 <Alert severity={user?.numberOfRequests > 0 ? "success" : "warning"}>This user has opened {user?.numberOfRequests} requests.</Alert> | ||||
|                             </Grid> | ||||
|                             <Grid item xs={12}> | ||||
|                                 <Alert severity={user?.amountSpent > 0 ? "success" : "warning"}>This user has paid {user?.amountSpent} for {user?.numberOfPaid} requests.</Alert> | ||||
|                             </Grid> | ||||
|                             <Grid item xs={12}> | ||||
|                                 <Alert severity={user?.numberOfReviews > 0 ? "success" : "warning"}>This user has left {user?.numberOfReviews} reviews on completed requests.</Alert> | ||||
|                             </Grid> | ||||
|                         </Grid> | ||||
|                     </Grid> | ||||
|                 </Grid> | ||||
|             </CardContent> | ||||
|         </Card> | ||||
|         </> | ||||
|   ); | ||||
| }; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Damien Ostler
						Damien Ostler