From 2a405067d871f4ff27daa29e95fe752eff040870 Mon Sep 17 00:00:00 2001 From: Damien Ostler Date: Sun, 17 Mar 2024 06:47:37 -0400 Subject: [PATCH] feat: added pages for viewing artist access requests, users, and artists in the admin menus --- components/AppAppBar.tsx | 3 +- components/dashboard/artist/reviews.tsx | 18 ++-- components/test.tsx | 0 pages/api/admin/artists/[artistId].tsx | 2 +- pages/api/admin/requests/[requestId].tsx | 5 +- .../messages.tsx} | 0 pages/api/artist/artistAccessRequest.tsx | 16 ++++ pages/dashboard/admin/artists.tsx | 2 +- pages/dashboard/admin/artists/[artistId].tsx | 84 +++++++++++++++- .../dashboard/admin/requests/[requestId].tsx | 96 ++++++++++++++++++- pages/dashboard/admin/users.tsx | 4 +- pages/dashboard/admin/users/[userId].tsx | 86 ++++++++++++++++- 12 files changed, 284 insertions(+), 32 deletions(-) create mode 100644 components/test.tsx rename pages/api/artist/{newRequest.tsx => [artistAccessRequestId]/messages.tsx} (100%) create mode 100644 pages/api/artist/artistAccessRequest.tsx diff --git a/components/AppAppBar.tsx b/components/AppAppBar.tsx index a0ebf47..d012893 100644 --- a/components/AppAppBar.tsx +++ b/components/AppAppBar.tsx @@ -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', diff --git a/components/dashboard/artist/reviews.tsx b/components/dashboard/artist/reviews.tsx index 34de384..8f620f0 100644 --- a/components/dashboard/artist/reviews.tsx +++ b/components/dashboard/artist/reviews.tsx @@ -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(); @@ -30,15 +26,19 @@ export default function Reviews({artistId}) { const getReviews = async () => { setIsLoading(true); const response = await fetch('/api/discovery/artist/'+artistId+'/reviews', { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - } + method: 'GET', + headers: { + 'Content-Type': 'application/json', + } }); 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', diff --git a/components/test.tsx b/components/test.tsx new file mode 100644 index 0000000..e69de29 diff --git a/pages/api/admin/artists/[artistId].tsx b/pages/api/admin/artists/[artistId].tsx index 53b6099..a5227a7 100644 --- a/pages/api/admin/artists/[artistId].tsx +++ b/pages/api/admin/artists/[artistId].tsx @@ -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}` } diff --git a/pages/api/admin/requests/[requestId].tsx b/pages/api/admin/requests/[requestId].tsx index 56dea25..d23f064 100644 --- a/pages/api/admin/requests/[requestId].tsx +++ b/pages/api/admin/requests/[requestId].tsx @@ -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); }); diff --git a/pages/api/artist/newRequest.tsx b/pages/api/artist/[artistAccessRequestId]/messages.tsx similarity index 100% rename from pages/api/artist/newRequest.tsx rename to pages/api/artist/[artistAccessRequestId]/messages.tsx diff --git a/pages/api/artist/artistAccessRequest.tsx b/pages/api/artist/artistAccessRequest.tsx new file mode 100644 index 0000000..49fec01 --- /dev/null +++ b/pages/api/artist/artistAccessRequest.tsx @@ -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); +}); + diff --git a/pages/dashboard/admin/artists.tsx b/pages/dashboard/admin/artists.tsx index 28ab83d..0deb943 100644 --- a/pages/dashboard/admin/artists.tsx +++ b/pages/dashboard/admin/artists.tsx @@ -65,7 +65,7 @@ export default function AdminArtists() { } }}, { field: 'actions', headerName: '', flex: 0.05, sortable: false, filterable: false, renderCell: (params) => { - return router.push("/dashboard/admin/users/"+params.row.id)}> + return router.push("/dashboard/admin/artists/"+params.row.id)}> }} ]; } diff --git a/pages/dashboard/admin/artists/[artistId].tsx b/pages/dashboard/admin/artists/[artistId].tsx index cf8d73b..3aa72af 100644 --- a/pages/dashboard/admin/artists/[artistId].tsx +++ b/pages/dashboard/admin/artists/[artistId].tsx @@ -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 ( + <> + + + + + Artist Information + + + + + + + + + + + + + + router.push("/dashboard/admin/artists")} color="primary"> + + + + + + + + + + Display Name: {artist?.user?.displayName} + + + Email: {artist?.user?.email} + + + + + + + + + + + 0 ? "error" : "success"}>{artist?.numberOfBans > 0 ? "This user has been banned "+artist?.numberOfBans+" times." : "This user has not been banned before."} + + + 0 ? "error" : "success"}>{artist?.numberOfBans > 0 ? "This user has been suspended "+artist?.numberOfSuspensions+" times." : "This user has not been suspended before."} + + + + + + + This artist has made ${artist?.amountMade}, and we have made ${artist?.feesCollected} in fees. + + + 0 ? "success" : "warning"}>This artist has accepted {artist?.numberOfRequests} requests. + + + 0 ? "success" : "warning"}>This artist has completed {artist?.numberOfCompleted} requests. + + + + + + + ); }; // Protected route, checking user authentication client-side.(CSR) -export default withPageAuthRequired(ArtistRequestDetails); +export default withPageAuthRequired(AdminArtist); diff --git a/pages/dashboard/admin/requests/[requestId].tsx b/pages/dashboard/admin/requests/[requestId].tsx index 1a2f282..8baf255 100644 --- a/pages/dashboard/admin/requests/[requestId].tsx +++ b/pages/dashboard/admin/requests/[requestId].tsx @@ -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 ( + <> + + + + + {router.query.requestId} - Artist Access Request + + + + router.push("/dashboard/admin/requests")} color="primary"> + + + + + + + + Submitted on {formattedTime} + + {request?.accepted ? ( + + This artist access request has been accepted. + + ):( + + Pending review from platform administrator. + + )} + + + {request?.message} + + + + + + + + + + + + + + + + ); }; diff --git a/pages/dashboard/admin/users.tsx b/pages/dashboard/admin/users.tsx index 6a6885c..452f2c4 100644 --- a/pages/dashboard/admin/users.tsx +++ b/pages/dashboard/admin/users.tsx @@ -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){ diff --git a/pages/dashboard/admin/users/[userId].tsx b/pages/dashboard/admin/users/[userId].tsx index 925c63f..c753630 100644 --- a/pages/dashboard/admin/users/[userId].tsx +++ b/pages/dashboard/admin/users/[userId].tsx @@ -2,23 +2,99 @@ 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 [user, setUser] = useState(null); + const getData = async () => { - if(router.query.artistId!=null){ - + 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 ( + <> + + + + + User Information + + + + + + + + + + + + + + router.push("/dashboard/admin/users")} color="primary"> + + + + + + + + + + Display Name: {user?.displayName} + + + Email: {user?.email} + + + + + + + + + + + 0 ? "error" : "success"}>{user?.numberOfBans > 0 ? "This user has been banned "+user?.numberOfBans+" times." : "This user has not been banned before."} + + + 0 ? "error" : "success"}>{user?.numberOfBans > 0 ? "This user has been suspended "+user?.numberOfSuspensions+" times." : "This user has not been suspended before."} + + + + + + + 0 ? "success" : "warning"}>This user has opened {user?.numberOfRequests} requests. + + + 0 ? "success" : "warning"}>This user has paid {user?.amountSpent} for {user?.numberOfPaid} requests. + + + 0 ? "success" : "warning"}>This user has left {user?.numberOfReviews} reviews on completed requests. + + + + + + + ); };