feat: admin list pages and apis

This commit is contained in:
Damien Ostler 2024-03-03 16:03:22 -05:00
parent ff465278ad
commit 5a2f43768d
35 changed files with 857 additions and 1116 deletions

View File

@ -8,7 +8,7 @@ import ListIcon from '@mui/icons-material/List';
// ** Type import
import { VerticalNavItemsType } from '../../core/layouts/types'
import { BankTransfer, Cart, Clipboard, PageFirst, StarOutline } from 'mdi-material-ui'
import { DocumentScanner, FileOpen, OpenInBrowser, Settings, WebAsset } from '@mui/icons-material'
import { DocumentScanner, FileOpen, LockPerson, OpenInBrowser, People, PeopleOutline, Settings, WebAsset } from '@mui/icons-material'
import { useState, useEffect } from 'react'
const navigation = (): VerticalNavItemsType => {
@ -46,10 +46,20 @@ const navigation = (): VerticalNavItemsType => {
sectionTitle: 'Admin'
},
{
title: 'Artist Requests',
icon: Clipboard,
title: 'Manage Artist Access',
icon: LockPerson,
path: '/dashboard/admin/requests'
},
{
title: 'Manage Users',
icon: People,
path: '/dashboard/admin/users'
},
{
title: 'Manage Artists',
icon: PeopleOutline,
path: '/dashboard/admin/artists'
},
{
sectionTitle: 'General'
},

View File

@ -1,103 +0,0 @@
// ** React Imports
import { SyntheticEvent, useState } from 'react'
// ** MUI Imports
import Box from '@mui/material/Box'
import Card from '@mui/material/Card'
import TabList from '@mui/lab/TabList'
import TabPanel from '@mui/lab/TabPanel'
import TabContext from '@mui/lab/TabContext'
import { styled } from '@mui/material/styles'
import MuiTab, { TabProps } from '@mui/material/Tab'
// ** Icons Imports
import AccountOutline from 'mdi-material-ui/AccountOutline'
import LockOpenOutline from 'mdi-material-ui/LockOpenOutline'
import InformationOutline from 'mdi-material-ui/InformationOutline'
// ** Demo Tabs Imports
import TabInfo from '../../views/account-settings/TabInfo'
import TabAccount from '../../views/account-settings/TabAccount'
import TabSecurity from '../../views/account-settings/TabSecurity'
// ** Third Party Styles Imports
import 'react-datepicker/dist/react-datepicker.css'
const Tab = styled(MuiTab)<TabProps>(({ theme }) => ({
[theme.breakpoints.down('md')]: {
minWidth: 100
},
[theme.breakpoints.down('sm')]: {
minWidth: 67
}
}))
const TabName = styled('span')(({ theme }) => ({
lineHeight: 1.71,
fontSize: '0.875rem',
marginLeft: theme.spacing(2.4),
[theme.breakpoints.down('md')]: {
display: 'none'
}
}))
const AccountSettings = () => {
// ** State
const [value, setValue] = useState<string>('account')
const handleChange = (event: SyntheticEvent, newValue: string) => {
setValue(newValue)
}
return (
<Card>
<TabContext value={value}>
<TabList
onChange={handleChange}
aria-label='account-settings tabs'
sx={{ borderBottom: theme => `1px solid ${theme.palette.divider}` }}
>
<Tab
value='account'
label={
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<AccountOutline />
<TabName>Account</TabName>
</Box>
}
/>
<Tab
value='security'
label={
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<LockOpenOutline />
<TabName>Security</TabName>
</Box>
}
/>
<Tab
value='info'
label={
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<InformationOutline />
<TabName>Info</TabName>
</Box>
}
/>
</TabList>
<TabPanel sx={{ p: 0 }} value='account'>
<TabAccount />
</TabPanel>
<TabPanel sx={{ p: 0 }} value='security'>
<TabSecurity />
</TabPanel>
<TabPanel sx={{ p: 0 }} value='info'>
<TabInfo />
</TabPanel>
</TabContext>
</Card>
)
}
export default AccountSettings

View File

@ -1,37 +0,0 @@
import { useEffect, useState } from "react";
import { useUser } from "@auth0/nextjs-auth0/client";
import Layout from "../../components/Old/layout";
const ApiProfile = () => {
const { user, isLoading } = useUser();
const [data, setData] = useState(null);
useEffect(() => {
(async () => {
const res = await fetch("/api/protected-api");
const data = await res.json();
setData(data);
})();
}, []);
return (
<Layout user={user} loading={isLoading}>
<h1>Profile</h1>
<div>
<h3>Public page (client rendered)</h3>
<p>We are fetching data on the client-side :</p>
<p>By making request to '/api/protected-api' serverless function</p>
<p>so without a valid session cookie will fail</p>
<p>{JSON.stringify(data)}</p>
</div>
</Layout>
);
};
// Public route.(CSR) also accessing API from the client-side.
// data is not cached when redirecting between pages.
export default ApiProfile;

View File

@ -1,26 +0,0 @@
import { withPageAuthRequired } from "@auth0/nextjs-auth0";
import Layout from "../../components/Old/layout";
import { User } from "../../interfaces";
type ProfileProps = {
user: User;
};
export default function Profile({ user }: ProfileProps) {
return (
<Layout user={user}>
<h1>Profile</h1>
<div>
<h3>Profile (server rendered)</h3>
<img src={user.picture} alt="user picture" />
<p>nickname: {user.nickname}</p>
<p>name: {user.name}</p>
</div>
</Layout>
);
}
// Protected route, checking authentication status before rendering the page.(SSR)
// It's slower than a static page with client side authentication
export const getServerSideProps = withPageAuthRequired();

View File

@ -0,0 +1,18 @@
import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-auth0';
export default withApiAuthRequired(async function onboardUrl(req, res) {
const { accessToken } = await getAccessToken(req, res);
const { offset, pageSize } = req.body;
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminArtists?offset='+offset+'&pageSize='+pageSize, {
headers: {
"Authorization": `Bearer ${accessToken}`
}
});
if(response.ok==false){
res.status(200).json({})
return;
}
let result = await response.json();
res.status(200).json(result);
});

View File

@ -0,0 +1,18 @@
import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-auth0';
export default withApiAuthRequired(async function onboardUrl(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, {
headers: {
"Authorization": `Bearer ${accessToken}`
}
});
if(response.ok==false){
res.status(200).json({})
return;
}
let result = await response.json();
res.status(200).json(result);
});

View File

@ -0,0 +1,19 @@
import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-auth0';
export default withApiAuthRequired(async function onboardUrl(req, res) {
const { accessToken } = await getAccessToken(req, res);
const { userId } = req.query;
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminArtists/'+userId+"/Suspend", {
headers: {
"Authorization": `Bearer ${accessToken}`
},
method: req.method
});
if(response.ok==false){
res.status(200).json({})
return;
}
let result = await response.json();
res.status(200).json(result);
});

View File

@ -0,0 +1,19 @@
import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-auth0';
export default withApiAuthRequired(async function onboardUrl(req, res) {
const { accessToken } = await getAccessToken(req, res);
const { userId } = req.query;
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminArtists/'+userId+"/Terminate", {
headers: {
"Authorization": `Bearer ${accessToken}`
},
method: req.method
});
if(response.ok==false){
res.status(200).json({})
return;
}
let result = await response.json();
res.status(200).json(result);
});

View File

@ -0,0 +1,19 @@
import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-auth0';
export default withApiAuthRequired(async function onboardUrl(req, res) {
const { accessToken } = await getAccessToken(req, res);
const { userId } = req.query;
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminArtists/'+userId+"/Unsuspend", {
headers: {
"Authorization": `Bearer ${accessToken}`
},
method: req.method
});
if(response.ok==false){
res.status(200).json({})
return;
}
let result = await response.json();
res.status(200).json(result);
});

View File

@ -0,0 +1,16 @@
import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-auth0';
export default withApiAuthRequired(async function onboardUrl(req, res) {
const { accessToken } = await getAccessToken(req, res);
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminArtists/Count', {
headers: {
"Authorization": `Bearer ${accessToken}`
}
});
if(response.ok==false){
res.status(200).json({})
return;
}
let result = await response.json();
res.status(200).json(result);
});

View File

@ -2,7 +2,8 @@ import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-a
export default withApiAuthRequired(async function onboardUrl(req, res) {
const { accessToken } = await getAccessToken(req, res);
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminArtistRequests', {
const { offset, pageSize } = req.body;
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminArtistRequests?offset='+offset+'&pageSize='+pageSize, {
headers: {
"Authorization": `Bearer ${accessToken}`
}

View File

@ -0,0 +1,20 @@
import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-auth0';
export default withApiAuthRequired(async function onboardUrl(req, res) {
const { accessToken } = await getAccessToken(req, res);
const { requestId } = req.query;
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminArtistRequests/'+requestId, {
headers: {
"Authorization": `Bearer ${accessToken}`,
},
method: req.method
});
if(response.ok==false){
res.status(200).json({})
return;
}
let result = await response.json();
res.status(200).json(result);
});
// handles ACCEPT AND DENY

View File

@ -0,0 +1,16 @@
import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-auth0';
export default withApiAuthRequired(async function onboardUrl(req, res) {
const { accessToken } = await getAccessToken(req, res);
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminArtistRequests/Count', {
headers: {
"Authorization": `Bearer ${accessToken}`
}
});
if(response.ok==false){
res.status(200).json({})
return;
}
let result = await response.json();
res.status(200).json(result);
});

18
pages/api/admin/users.tsx Normal file
View File

@ -0,0 +1,18 @@
import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-auth0';
export default withApiAuthRequired(async function onboardUrl(req, res) {
const { accessToken } = await getAccessToken(req, res);
const { offset, pageSize } = req.body;
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminUsers?offset='+offset+'&pageSize='+pageSize, {
headers: {
"Authorization": `Bearer ${accessToken}`
}
});
if(response.ok==false){
res.status(200).json({})
return;
}
let result = await response.json();
res.status(200).json(result);
});

View File

@ -0,0 +1,18 @@
import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-auth0';
export default withApiAuthRequired(async function onboardUrl(req, res) {
const { accessToken } = await getAccessToken(req, res);
const { userId } = req.query;
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminUsers/'+userId, {
headers: {
"Authorization": `Bearer ${accessToken}`
}
});
if(response.ok==false){
res.status(200).json({})
return;
}
let result = await response.json();
res.status(200).json(result);
});

View File

@ -3,9 +3,9 @@ import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-a
export default withApiAuthRequired(async function onboardUrl(req, res) {
const { accessToken } = await getAccessToken(req, res);
const { userId } = req.query;
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminArtistRequests/'+userId, {
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminUsers/'+userId+"/Ban", {
headers: {
"Authorization": `Bearer ${accessToken}`,
"Authorization": `Bearer ${accessToken}`
},
method: req.method
});

View File

@ -0,0 +1,19 @@
import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-auth0';
export default withApiAuthRequired(async function onboardUrl(req, res) {
const { accessToken } = await getAccessToken(req, res);
const { userId } = req.query;
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminUsers/'+userId+"/Suspend", {
headers: {
"Authorization": `Bearer ${accessToken}`
},
method: req.method
});
if(response.ok==false){
res.status(200).json({})
return;
}
let result = await response.json();
res.status(200).json(result);
});

View File

@ -0,0 +1,19 @@
import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-auth0';
export default withApiAuthRequired(async function onboardUrl(req, res) {
const { accessToken } = await getAccessToken(req, res);
const { userId } = req.query;
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminUsers/'+userId+"/Unban", {
headers: {
"Authorization": `Bearer ${accessToken}`
},
method: req.method
});
if(response.ok==false){
res.status(200).json({})
return;
}
let result = await response.json();
res.status(200).json(result);
});

View File

@ -0,0 +1,19 @@
import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-auth0';
export default withApiAuthRequired(async function onboardUrl(req, res) {
const { accessToken } = await getAccessToken(req, res);
const { userId } = req.query;
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminUsers/'+userId+"/Unsuspend", {
headers: {
"Authorization": `Bearer ${accessToken}`
},
method: req.method
});
if(response.ok==false){
res.status(200).json({})
return;
}
let result = await response.json();
res.status(200).json(result);
});

View File

@ -0,0 +1,16 @@
import { getAccessToken, withApiAuthRequired, getSession } from '@auth0/nextjs-auth0';
export default withApiAuthRequired(async function onboardUrl(req, res) {
const { accessToken } = await getAccessToken(req, res);
const response = await fetch(process.env.NEXT_PUBLIC_API_URL+'/api/admin/AdminUsers/Count', {
headers: {
"Authorization": `Bearer ${accessToken}`
}
});
if(response.ok==false){
res.status(200).json({})
return;
}
let result = await response.json();
res.status(200).json(result);
});

View File

@ -7,7 +7,9 @@ export default withApiAuthRequired(async function onboardUrl(req, res) {
"Authorization": `Bearer ${accessToken}`
}
});
if(response.ok==false){
res.status(200).json({})
}
let result = await response.json();
res.status(200).json(result);
});

View File

@ -1,83 +0,0 @@
// ** MUI Imports
import Grid from '@mui/material/Grid'
import Typography from '@mui/material/Typography'
// ** Demo Components Imports
import CardUser from '../views/cards/CardUser'
import CardImgTop from '../views/cards/CardImgTop'
import CardMobile from '../views/cards/CardMobile'
import CardSupport from '../views/cards/CardSupport'
import CardTwitter from '../views/cards/CardTwitter'
import CardFacebook from '../views/cards/CardFacebook'
import CardLinkedIn from '../views/cards/CardLinkedIn'
import CardAppleWatch from '../views/cards/CardAppleWatch'
import CardMembership from '../views/cards/CardMembership'
import CardInfluencer from '../views/cards/CardInfluencer'
import CardNavigation from '../views/cards/CardNavigation'
import CardWithCollapse from '../views/cards/CardWithCollapse'
import CardVerticalRatings from '../views/cards/CardVerticalRatings'
import CardNavigationCenter from '../views/cards/CardNavigationCenter'
import CardHorizontalRatings from '../views/cards/CardHorizontalRatings'
const CardBasic = () => {
return (
<Grid container spacing={6}>
<Grid item xs={12} sx={{ paddingBottom: 4 }}>
<Typography variant='h5'>Basic Cards</Typography>
</Grid>
<Grid item xs={12} sm={6} md={4}>
<CardImgTop />
</Grid>
<Grid item xs={12} sm={6} md={4}>
<CardUser />
</Grid>
<Grid item xs={12} sm={6} md={4}>
<CardWithCollapse />
</Grid>
<Grid item xs={12} sm={6}>
<CardMobile />
</Grid>
<Grid item xs={12} sm={6}>
<CardHorizontalRatings />
</Grid>
<Grid item xs={12} sm={6} md={4}>
<CardAppleWatch />
</Grid>
<Grid item xs={12} md={8}>
<CardMembership />
</Grid>
<Grid item xs={12} sm={6} md={4}>
<CardInfluencer />
</Grid>
<Grid item xs={12} sm={6} md={4}>
<CardVerticalRatings />
</Grid>
<Grid item xs={12} sm={6} md={4}>
<CardSupport />
</Grid>
<Grid item xs={12} sx={{ pb: 4, pt: theme => `${theme.spacing(17.5)} !important` }}>
<Typography variant='h5'>Navigation Cards</Typography>
</Grid>
<Grid item xs={12} md={6}>
<CardNavigation />
</Grid>
<Grid item xs={12} md={6}>
<CardNavigationCenter />
</Grid>
<Grid item xs={12} sx={{ pb: 4, pt: theme => `${theme.spacing(17.5)} !important` }}>
<Typography variant='h5'>Solid Cards</Typography>
</Grid>
<Grid item xs={12} sm={6} md={4}>
<CardTwitter />
</Grid>
<Grid item xs={12} sm={6} md={4}>
<CardFacebook />
</Grid>
<Grid item xs={12} sm={6} md={4}>
<CardLinkedIn />
</Grid>
</Grid>
)
}
export default CardBasic

View File

@ -0,0 +1,151 @@
import * as React from 'react';
import { DataGrid } from '@mui/x-data-grid';
import { GridColDef } from '@mui/x-data-grid';
import TextField from '@mui/material/TextField';
import { Button, Stack, Typography } from '@mui/material';
import CurrencyTextField from '@lupus-ai/mui-currency-textfield';
import { DateField } from '@mui/x-date-pickers/DateField';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import Chip from '@mui/material/Chip';
import {Block, Check, Close, Download, OpenInFull, OpenInNew, Refresh, Star, Upload } from '@mui/icons-material';
import PriceCheckIcon from '@mui/icons-material/PriceCheck';
import AssignmentTurnedInIcon from '@mui/icons-material/AssignmentTurnedIn';
import AssignmentLateIcon from '@mui/icons-material/AssignmentLate';
import ShoppingCartCheckoutIcon from '@mui/icons-material/ShoppingCartCheckout';
import { IconButton } from '@mui/material';
import Tooltip from '@mui/material/Tooltip';
import { Card, CardContent } from '@mui/material';
import Rating from '@mui/material/Rating';
import dayjs from 'dayjs';
import { DownloadBox, Magnify, StarOutline } from 'mdi-material-ui';
import { Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, FormControl, InputLabel, Box } from '@mui/material';
import { Grid } from '@mui/material';
import { useRouter } from 'next/router';
import { request } from 'http';
import { useMediaQuery } from '@mui/material';
export default function AdminArtists() {
const isSmallScreen = useMediaQuery(theme => theme.breakpoints.down('sm')); // Check if the screen size is small
const router = useRouter();
let columns = [];
if(isSmallScreen){
columns = [
{ field: 'id', headerName: '', flex: 0.05, sortable: false, filterable: false},
];
}
else{
columns = [
{ field: 'id', headerName: '', flex: 0.05, sortable: false, filterable: false},
{ field: 'displayName', headerName: 'User Name', flex: 0.15, sortable: false, filterable: false, valueGetter: (params) => {
return params.row.user.displayName
}},
{ field: 'name', headerName: 'Artist Name', flex: 0.15, sortable: false, filterable: false, valueGetter: (params) => {
return params.row.name
}},
{ field: 'email', headerName: 'Email', flex: 0.15, sortable: false, filterable: false, valueGetter: (params) => {
return params.row.user.email
}},
{ field: 'numberOfRequests', headerName: '# of Requests', flex: 0.1, sortable: false, filterable: false},
{ field: 'averageRating', headerName: 'Average Rating', flex: 0.1, sortable: false, filterable: false},
{ field: 'amountMade', headerName: 'Amount Made', flex: 0.1, sortable: false, filterable: false},
{ field: 'feesCollected', headerName: 'Fees Collected', flex: 0.1, sortable: false, filterable: false},
{ field: 'status', headerName: 'Status', flex: 0.1, sortable: false, filterable: false, renderCell: (params) =>{
if(params.row.user.banned){
return <Chip icon={<Block />} label="Banned" variant="outlined" color="error" />
}
else if(params.row.suspended || params.row.user.suspended){
return <Chip icon={<Block />} label="Suspended" variant="outlined" color="error" />
}
else{
return <Chip icon={<Check />} label="Active" variant="outlined" color="success" />
}
}},
{ 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>
}}
];
}
const [isLoading, setIsLoading] = React.useState(true);
const [requestCount, setRequestCount] = React.useState(null);
const [requestData, setRequestData] = React.useState({});
const [paginationModel, setPaginationModel] = React.useState({
page: 0,
pageSize: 15,
});
const getRequests = async () => {
setIsLoading(true);
const response = await fetch('/api/admin/artists', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
completed: true, // Example query parameter
declined: true, // Example query parameter
accepted: true, // Example query parameter
paid: true, // Example query parameter
offset: paginationModel.page*paginationModel.pageSize, // Example query parameter
pageSize: paginationModel.pageSize
}),
});
const data = await response.json();
setRequestData(data);
setIsLoading(false);
}
const getRequestsCount = async () => {
const response = await fetch('/api/admin/artists/count', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
completed: true, // Example query parameter
declined: true, // Example query parameter
accepted: true, // Example query parameter
paid: true, // Example query parameter
offset: paginationModel.page*paginationModel.pageSize, // Example query parameter
pageSize: paginationModel.pageSize
})
});
const data = await response.json();
setRequestCount(data);
setRowCountState((prevRowCountState) =>
data !== undefined
? data
: prevRowCountState,
);
return data;
}
// Some API clients return undefined while loading
// Following lines are here to prevent `rowCountState` from being undefined during the loading
const [rowCountState, setRowCountState] = React.useState(0);
React.useEffect(() => {
getRequests();
getRequestsCount();
}, [requestCount, setRowCountState,paginationModel]);
return (
<div style={{ height: '100%', width: '100%' }}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DataGrid
rows={requestData}
columns={columns}
rowCount={rowCountState}
loading={isLoading}
pageSizeOptions={[15]}
paginationModel={paginationModel}
paginationMode="server"
onPaginationModelChange={setPaginationModel}
/>
</LocalizationProvider>
</div>
);
}

View File

@ -0,0 +1,28 @@
import * as React from 'react';
import { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import { withPageAuthRequired } from '@auth0/nextjs-auth0/client'
const AdminArtist = () => {
const router = useRouter();
const getData = async () => {
if(router.query.artistId!=null){
}
}
useEffect(() => {
getData()
}, [router.query.artistId]);
return (<>
</>
);
};
// Protected route, checking user authentication client-side.(CSR)
export default withPageAuthRequired(ArtistRequestDetails);

View File

@ -1,50 +1,206 @@
import { useUser,withPageAuthRequired } from "@auth0/nextjs-auth0/client";
import { Grid, Typography } from "@mui/material";
import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
import EditableArtistPortfolio from "../../../components/Old/editableArtistPortfolio";
import { useEffect, useState } from "react";
import * as React from 'react';
import { DataGrid } from '@mui/x-data-grid';
import { GridColDef } from '@mui/x-data-grid';
import TextField from '@mui/material/TextField';
import Button from '@mui/material/Button';
import Switch from '@mui/material/Switch';
import Divider from '@mui/material/Divider';
import ArtistRequest from "../../../components/dashboard/admin/artistRequest";
import { Button, Stack, Typography } from '@mui/material';
import CurrencyTextField from '@lupus-ai/mui-currency-textfield';
import { DateField } from '@mui/x-date-pickers/DateField';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import Chip from '@mui/material/Chip';
import {Block, Check, Close, Download, OpenInFull, OpenInNew, Person, Refresh, Star, Upload } from '@mui/icons-material';
import PriceCheckIcon from '@mui/icons-material/PriceCheck';
import AssignmentTurnedInIcon from '@mui/icons-material/AssignmentTurnedIn';
import AssignmentLateIcon from '@mui/icons-material/AssignmentLate';
import ShoppingCartCheckoutIcon from '@mui/icons-material/ShoppingCartCheckout';
import { IconButton } from '@mui/material';
import Tooltip from '@mui/material/Tooltip';
import { Card, CardContent } from '@mui/material';
import Rating from '@mui/material/Rating';
const ArtistRequests = () => {
const {user, isLoading} = useUser();
const [artistRequestData, setArtistRequestData] = useState(null);
const getData = () => {
fetch('/api/admin/requests').then(response => response.json().then(data => setArtistRequestData(data)))
}
useEffect(() => {
getData()
}, []);
return (
<Grid container spacing={2}>
{(artistRequestData != null && Object.keys(artistRequestData).length>0) ? (
(artistRequestData.map((request) => {
let formattedTime = "";
if (artistRequestData) {
const date = new Date(request["requestDate"]);
formattedTime = date.toLocaleTimeString('en-US', {
month: 'long',
day: '2-digit',
year: 'numeric',
hour12: true,
hour: '2-digit',
minute: '2-digit'
}); // Example format
import dayjs from 'dayjs';
import { DownloadBox, Magnify, StarOutline } from 'mdi-material-ui';
import { Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, FormControl, InputLabel, Box } from '@mui/material';
import { Grid } from '@mui/material';
import { useRouter } from 'next/router';
import { request } from 'http';
import { useMediaQuery } from '@mui/material';
export default function AdminRequests() {
const isSmallScreen = useMediaQuery(theme => theme.breakpoints.down('sm')); // Check if the screen size is small
const router = useRouter();
let columns = [];
if(isSmallScreen){
columns = [
{ field: 'id', headerName: '', flex: 0.05, sortable: false, filterable: false},
{ field: 'message', headerName: 'Message', flex: 0.2, sortable: false, filterable: false},
{ field: 'actions', headerName: '', flex: 0.15, sortable: false, filterable: false, renderCell: (params) => {
const handleAccept = async () => {
var response = await fetch("/api/admin/requests/"+params.row.userId, {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/"+params.row.userId, {method:"DELETE"})
if(response.ok){
var data = await response.json();
router.reload();
}
else{
alert("Failed to deny request.")
}
}
if(params.row.accepted){
return <>
<Tooltip title="Revoke artist access"><IconButton color="error"><Block/></IconButton></Tooltip>
<Tooltip title="View artist information"><IconButton onClick={() => router.push("/dashboard/admin/requests/"+params.row.id)} color="info"><Magnify/></IconButton></Tooltip>
</>
}
else{
return (
<>
<Tooltip title="Accept this request and grant artist access."><IconButton onClick={handleAccept} color="success"><Check/></IconButton></Tooltip>
<Tooltip title="Decline this request and refuse artist access."><IconButton onClick={handleDeny} color="error"><Close/></IconButton></Tooltip>
</>
)
}
}}
];
}
else{
columns = [
{ field: 'id', headerName: '', flex: 0.05, sortable: false, filterable: false},
{ field: 'userId', headerName: 'User ID', flex: 0.25, sortable: false, filterable: false},
{ field: 'message', headerName: 'Message', flex: 0.5, sortable: false, filterable: false},
{ field: 'requestDate', headerName: 'Request Date', flex: 0.1, sortable: false, filterable: false, type: 'date', valueGetter: (params) => { return new Date(params.row.requestDate); }},
{ field: 'accepted', headerName:'Accepted', flex: 0.15, sortable: false, filterable: false, renderCell: (params) => {
return (params.row.accepted ? <Chip icon={<Check />} label="Accepted" variant="outlined" color="success" /> : <Chip icon={<Refresh />} label="Pending" variant="outlined" color="info" />)
}},
{ field: 'actions', headerName: '', flex: 0.15, sortable: false, filterable: false, renderCell: (params) => {
const handleAccept = async () => {
var response = await fetch("/api/admin/requests/"+params.row.userId, {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/"+params.row.userId, {method:"DELETE"})
if(response.ok){
var data = await response.json();
router.reload();
}
else{
alert("Failed to deny request.")
}
}
if(params.row.accepted){
return <>
<Tooltip title="View request information"><IconButton onClick={() => router.push("/dashboard/admin/requests/"+params.row.id)} color="info"><OpenInNew/></IconButton></Tooltip>
<Tooltip title="View artist information"><IconButton onClick={() => router.push("/dashboard/admin/users/"+params.row.id)} color="info"><Person/></IconButton></Tooltip>
</>
}
else{
return (
<>
<Tooltip title="View request information"><IconButton onClick={() => router.push("/dashboard/admin/requests/"+params.row.id)} color="info"><OpenInNew/></IconButton></Tooltip>
<Tooltip title="Accept this request and grant artist access."><IconButton onClick={handleAccept} color="success"><Check/></IconButton></Tooltip>
<Tooltip title="Decline this request and refuse artist access."><IconButton onClick={handleDeny} color="error"><Close/></IconButton></Tooltip>
</>
)
}
}}
];
}
const [isLoading, setIsLoading] = React.useState(true);
const [requestCount, setRequestCount] = React.useState(null);
const [requestData, setRequestData] = React.useState({});
const [paginationModel, setPaginationModel] = React.useState({
page: 0,
pageSize: 15,
});
const getRequests = async () => {
setIsLoading(true);
const response = await fetch('/api/admin/requests', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
completed: true, // Example query parameter
declined: true, // Example query parameter
accepted: true, // Example query parameter
paid: true, // Example query parameter
offset: paginationModel.page*paginationModel.pageSize, // Example query parameter
pageSize: paginationModel.pageSize
}),
});
const data = await response.json();
setRequestData(data);
setIsLoading(false);
}
return (
<ArtistRequest userid={request["userId"]} id={request["id"]} username={""} message={request["message"]} date={formattedTime} reload={getData} />
)
}
))
):(<Typography>No requests</Typography>)}
</Grid>
);
};
const getRequestsCount = async () => {
const response = await fetch('/api/admin/requests/count', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
completed: true, // Example query parameter
declined: true, // Example query parameter
accepted: true, // Example query parameter
paid: true, // Example query parameter
offset: paginationModel.page*paginationModel.pageSize, // Example query parameter
pageSize: paginationModel.pageSize
})
});
const data = await response.json();
setRequestCount(data);
setRowCountState((prevRowCountState) =>
data !== undefined
? data
: prevRowCountState,
);
return data;
}
// Protected route, checking user authentication client-side.(CSR)
export default withPageAuthRequired(ArtistRequests);
// Some API clients return undefined while loading
// Following lines are here to prevent `rowCountState` from being undefined during the loading
const [rowCountState, setRowCountState] = React.useState(0);
React.useEffect(() => {
getRequests();
getRequestsCount();
}, [requestCount, setRowCountState,paginationModel]);
return (
<div style={{ height: '100%', width: '100%' }}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DataGrid
rows={requestData}
columns={columns}
rowCount={rowCountState}
loading={isLoading}
pageSizeOptions={[15]}
paginationModel={paginationModel}
paginationMode="server"
onPaginationModelChange={setPaginationModel}
/>
</LocalizationProvider>
</div>
);
}

View File

@ -0,0 +1,28 @@
import * as React from 'react';
import { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import { withPageAuthRequired } from '@auth0/nextjs-auth0/client'
const AdminRequest = () => {
const router = useRouter();
const getData = async () => {
if(router.query.artistId!=null){
}
}
useEffect(() => {
getData()
}, [router.query.artistId]);
return (<>
</>
);
};
// Protected route, checking user authentication client-side.(CSR)
export default withPageAuthRequired(AdminRequest);

View File

@ -0,0 +1,147 @@
import * as React from 'react';
import { DataGrid } from '@mui/x-data-grid';
import { GridColDef } from '@mui/x-data-grid';
import TextField from '@mui/material/TextField';
import { Button, Stack, Typography } from '@mui/material';
import CurrencyTextField from '@lupus-ai/mui-currency-textfield';
import { DateField } from '@mui/x-date-pickers/DateField';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import Chip from '@mui/material/Chip';
import {Block, Check, Close, Download, OpenInFull, OpenInNew, Refresh, Star, Upload } from '@mui/icons-material';
import PriceCheckIcon from '@mui/icons-material/PriceCheck';
import AssignmentTurnedInIcon from '@mui/icons-material/AssignmentTurnedIn';
import AssignmentLateIcon from '@mui/icons-material/AssignmentLate';
import ShoppingCartCheckoutIcon from '@mui/icons-material/ShoppingCartCheckout';
import { IconButton } from '@mui/material';
import Tooltip from '@mui/material/Tooltip';
import { Card, CardContent } from '@mui/material';
import Rating from '@mui/material/Rating';
import dayjs from 'dayjs';
import { DownloadBox, Magnify, StarOutline } from 'mdi-material-ui';
import { Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, FormControl, InputLabel, Box } from '@mui/material';
import { Grid } from '@mui/material';
import { useRouter } from 'next/router';
import { request } from 'http';
import { useMediaQuery } from '@mui/material';
export default function AdminUsers() {
const isSmallScreen = useMediaQuery(theme => theme.breakpoints.down('sm')); // Check if the screen size is small
const router = useRouter();
let columns = [];
if(isSmallScreen){
columns = [
{ field: 'id', headerName: 'User ID', flex: 0.95, sortable: false, filterable: false},
{ field: "actions", headerName: "Actions", 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>
}}
];
}
else{
columns = [
{ 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: "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){
return <Chip icon={<Block />} label="Banned" variant="outlined" color="error" />
}
else if(params.row.suspended){
return <Chip icon={<Block />} label="Suspended" variant="outlined" color="error" />
}
else{
return <Chip icon={<Check />} label="Active" variant="outlined" color="success" />
}
}},
{ 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>
}}
];
}
const [isLoading, setIsLoading] = React.useState(true);
const [requestCount, setRequestCount] = React.useState(null);
const [requestData, setRequestData] = React.useState({});
const [paginationModel, setPaginationModel] = React.useState({
page: 0,
pageSize: 15,
});
const getRequests = async () => {
setIsLoading(true);
const response = await fetch('/api/admin/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
completed: true, // Example query parameter
declined: true, // Example query parameter
accepted: true, // Example query parameter
paid: true, // Example query parameter
offset: paginationModel.page*paginationModel.pageSize, // Example query parameter
pageSize: paginationModel.pageSize
}),
});
const data = await response.json();
setRequestData(data);
setIsLoading(false);
}
const getRequestsCount = async () => {
const response = await fetch('/api/admin/users/count', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
completed: true, // Example query parameter
declined: true, // Example query parameter
accepted: true, // Example query parameter
paid: true, // Example query parameter
offset: paginationModel.page*paginationModel.pageSize, // Example query parameter
pageSize: paginationModel.pageSize
})
});
const data = await response.json();
setRequestCount(data);
setRowCountState((prevRowCountState) =>
data !== undefined
? data
: prevRowCountState,
);
return data;
}
// Some API clients return undefined while loading
// Following lines are here to prevent `rowCountState` from being undefined during the loading
const [rowCountState, setRowCountState] = React.useState(0);
React.useEffect(() => {
getRequests();
getRequestsCount();
}, [requestCount, setRowCountState,paginationModel]);
return (
<div style={{ height: '100%', width: '100%' }}>
<Button target="_blank" href="https://manage.auth0.com/dashboard">Open Auth0 Dashboard</Button>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DataGrid
rows={requestData}
columns={columns}
rowCount={rowCountState}
loading={isLoading}
pageSizeOptions={[15]}
paginationModel={paginationModel}
paginationMode="server"
onPaginationModelChange={setPaginationModel}
/>
</LocalizationProvider>
</div>
);
}

View File

@ -0,0 +1,28 @@
import * as React from 'react';
import { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import { withPageAuthRequired } from '@auth0/nextjs-auth0/client'
const AdminUser = () => {
const router = useRouter();
const getData = async () => {
if(router.query.artistId!=null){
}
}
useEffect(() => {
getData()
}, [router.query.artistId]);
return (<>
</>
);
};
// Protected route, checking user authentication client-side.(CSR)
export default withPageAuthRequired(AdminUser);

View File

@ -1,37 +0,0 @@
// ** MUI Imports
import Grid from '@mui/material/Grid'
// ** Styled Component
import DatePickerWrapper from '../../core/styles/libs/react-datepicker'
// ** Demo Components Imports
import FormLayoutsBasic from '../../views/form-layouts/FormLayoutsBasic'
import FormLayoutsIcons from '../../views/form-layouts/FormLayoutsIcons'
import FormLayoutsSeparator from '../../views/form-layouts/FormLayoutsSeparator'
import FormLayoutsAlignment from '../../views/form-layouts/FormLayoutsAlignment'
// ** Third Party Styles Imports
import 'react-datepicker/dist/react-datepicker.css'
const FormLayouts = () => {
return (
<DatePickerWrapper>
<Grid container spacing={6}>
<Grid item xs={12} md={6}>
<FormLayoutsBasic />
</Grid>
<Grid item xs={12} md={6}>
<FormLayoutsIcons />
</Grid>
<Grid item xs={12}>
<FormLayoutsSeparator />
</Grid>
<Grid item xs={12}>
<FormLayoutsAlignment />
</Grid>
</Grid>
</DatePickerWrapper>
)
}
export default FormLayouts

View File

@ -1,164 +0,0 @@
// ** MUI Imports
import Grid from '@mui/material/Grid'
import Card from '@mui/material/Card'
import Link from '@mui/material/Link'
import Button from '@mui/material/Button'
import Tooltip from '@mui/material/Tooltip'
import Typography from '@mui/material/Typography'
import CardContent from '@mui/material/CardContent'
/**
** Icons Imports:
* ! You need to import all the icons which come from the API or from your server and then add these icons in 'icons' variable.
* ! If you need all the icons from the library, use "import * as Icon from 'mdi-material-ui'"
* */
import Abacus from 'mdi-material-ui/Abacus'
import Account from 'mdi-material-ui/Account'
import AbTesting from 'mdi-material-ui/AbTesting'
import AccountBox from 'mdi-material-ui/AccountBox'
import AccountCog from 'mdi-material-ui/AccountCog'
import AbjadArabic from 'mdi-material-ui/AbjadArabic'
import AbjadHebrew from 'mdi-material-ui/AbjadHebrew'
import AbugidaThai from 'mdi-material-ui/AbugidaThai'
import AccessPoint from 'mdi-material-ui/AccessPoint'
import AccountCash from 'mdi-material-ui/AccountCash'
import AccountEdit from 'mdi-material-ui/AccountEdit'
import AccountAlert from 'mdi-material-ui/AccountAlert'
import AccountCheck from 'mdi-material-ui/AccountCheck'
import AccountChild from 'mdi-material-ui/AccountChild'
import AccountClock from 'mdi-material-ui/AccountClock'
import AccountGroup from 'mdi-material-ui/AccountGroup'
import AccountCancel from 'mdi-material-ui/AccountCancel'
import AccountCircle from 'mdi-material-ui/AccountCircle'
import AccessPointOff from 'mdi-material-ui/AccessPointOff'
import AccountConvert from 'mdi-material-ui/AccountConvert'
import AccountDetails from 'mdi-material-ui/AccountDetails'
import AccessPointPlus from 'mdi-material-ui/AccessPointPlus'
import AccessPointCheck from 'mdi-material-ui/AccessPointCheck'
import AccessPointMinus from 'mdi-material-ui/AccessPointMinus'
import AccountArrowLeft from 'mdi-material-ui/AccountArrowLeft'
import AccountCowboyHat from 'mdi-material-ui/AccountCowboyHat'
import AbugidaDevanagari from 'mdi-material-ui/AbugidaDevanagari'
import AccessPointRemove from 'mdi-material-ui/AccessPointRemove'
import AccountArrowRight from 'mdi-material-ui/AccountArrowRight'
import AccountBoxOutline from 'mdi-material-ui/AccountBoxOutline'
import AccountCogOutline from 'mdi-material-ui/AccountCogOutline'
import AccessPointNetwork from 'mdi-material-ui/AccessPointNetwork'
import AccountBoxMultiple from 'mdi-material-ui/AccountBoxMultiple'
import AccountCashOutline from 'mdi-material-ui/AccountCashOutline'
import AccountChildCircle from 'mdi-material-ui/AccountChildCircle'
import AccountEditOutline from 'mdi-material-ui/AccountEditOutline'
import AccountAlertOutline from 'mdi-material-ui/AccountAlertOutline'
import AccountCheckOutline from 'mdi-material-ui/AccountCheckOutline'
import AccountChildOutline from 'mdi-material-ui/AccountChildOutline'
import AccountClockOutline from 'mdi-material-ui/AccountClockOutline'
import AccountCancelOutline from 'mdi-material-ui/AccountCancelOutline'
import AccountCircleOutline from 'mdi-material-ui/AccountCircleOutline'
import AccessPointNetworkOff from 'mdi-material-ui/AccessPointNetworkOff'
import AccountConvertOutline from 'mdi-material-ui/AccountConvertOutline'
import AccountDetailsOutline from 'mdi-material-ui/AccountDetailsOutline'
import AccountArrowLeftOutline from 'mdi-material-ui/AccountArrowLeftOutline'
import AccountArrowRightOutline from 'mdi-material-ui/AccountArrowRightOutline'
import AccountBoxMultipleOutline from 'mdi-material-ui/AccountBoxMultipleOutline'
const icons = {
Abacus,
Account,
AbTesting,
AccountBox,
AccountCog,
AbjadArabic,
AbjadHebrew,
AbugidaThai,
AccessPoint,
AccountCash,
AccountEdit,
AccountAlert,
AccountCheck,
AccountChild,
AccountClock,
AccountGroup,
AccountCancel,
AccountCircle,
AccessPointOff,
AccountConvert,
AccountDetails,
AccessPointPlus,
AccessPointCheck,
AccessPointMinus,
AccountArrowLeft,
AccountCowboyHat,
AbugidaDevanagari,
AccessPointRemove,
AccountArrowRight,
AccountBoxOutline,
AccountCogOutline,
AccessPointNetwork,
AccountBoxMultiple,
AccountCashOutline,
AccountChildCircle,
AccountEditOutline,
AccountAlertOutline,
AccountCheckOutline,
AccountChildOutline,
AccountClockOutline,
AccountCancelOutline,
AccountCircleOutline,
AccessPointNetworkOff,
AccountConvertOutline,
AccountDetailsOutline,
AccountArrowLeftOutline,
AccountArrowRightOutline,
AccountBoxMultipleOutline
}
const Icons = () => {
const renderIconGrids = () => {
return Object.keys(icons).map(key => {
const IconTag = icons[key as keyof typeof icons]
return (
<Grid item key={key}>
<Tooltip arrow title={key} placement='top'>
<Card>
<CardContent sx={{ display: 'flex' }}>
<IconTag />
</CardContent>
</Card>
</Tooltip>
</Grid>
)
})
}
return (
<Grid container spacing={6}>
<Grid item xs={12}>
<Typography variant='h5'>
<Link href='https://materialdesignicons.com/' target='_blank'>
Material Design Icons
</Link>
</Typography>
<Typography variant='body2'>Material Design Icons from the Community</Typography>
</Grid>
<Grid item xs={12}>
<Grid container spacing={6}>
{renderIconGrids()}
</Grid>
</Grid>
<Grid item xs={12} sx={{ textAlign: 'center' }}>
<Button
target='_blank'
rel='noreferrer'
component={Link}
variant='contained'
href='https://materialdesignicons.com/'
>
View All Material Design Icons
</Button>
</Grid>
</Grid>
)
}
export default Icons

View File

@ -1,14 +0,0 @@
// ** React Imports
import { ReactNode } from 'react'
// ** Layout Import
import BlankLayout from '../core/layouts/BlankLayout'
// ** Component Import
import Error404 from '../pages/404'
const ErrorPage = () => <Error404 />
ErrorPage.getLayout = (page: ReactNode) => <BlankLayout>{page}</BlankLayout>
export default ErrorPage

View File

@ -1,257 +0,0 @@
// ** React Imports
import { ChangeEvent, MouseEvent, ReactNode, useState } from 'react'
// ** Next Imports
import Link from 'next/link'
import { useRouter } from 'next/router'
// ** MUI Components
import Box from '@mui/material/Box'
import Button from '@mui/material/Button'
import Divider from '@mui/material/Divider'
import Checkbox from '@mui/material/Checkbox'
import TextField from '@mui/material/TextField'
import InputLabel from '@mui/material/InputLabel'
import Typography from '@mui/material/Typography'
import IconButton from '@mui/material/IconButton'
import CardContent from '@mui/material/CardContent'
import FormControl from '@mui/material/FormControl'
import OutlinedInput from '@mui/material/OutlinedInput'
import { styled, useTheme } from '@mui/material/styles'
import MuiCard, { CardProps } from '@mui/material/Card'
import InputAdornment from '@mui/material/InputAdornment'
import MuiFormControlLabel, { FormControlLabelProps } from '@mui/material/FormControlLabel'
// ** Icons Imports
import Google from 'mdi-material-ui/Google'
import Github from 'mdi-material-ui/Github'
import Twitter from 'mdi-material-ui/Twitter'
import Facebook from 'mdi-material-ui/Facebook'
import EyeOutline from 'mdi-material-ui/EyeOutline'
import EyeOffOutline from 'mdi-material-ui/EyeOffOutline'
// ** Configs
import themeConfig from '../configs/themeConfig'
// ** Layout Import
import BlankLayout from '../core/layouts/BlankLayout'
// ** Demo Imports
import FooterIllustrationsV1 from '../views/pages/auth/FooterIllustration'
interface State {
password: string
showPassword: boolean
}
// ** Styled Components
const Card = styled(MuiCard)<CardProps>(({ theme }) => ({
[theme.breakpoints.up('sm')]: { width: '28rem' }
}))
const LinkStyled = styled('a')(({ theme }) => ({
fontSize: '0.875rem',
textDecoration: 'none',
color: theme.palette.primary.main
}))
const FormControlLabel = styled(MuiFormControlLabel)<FormControlLabelProps>(({ theme }) => ({
'& .MuiFormControlLabel-label': {
fontSize: '0.875rem',
color: theme.palette.text.secondary
}
}))
const LoginPage = () => {
// ** State
const [values, setValues] = useState<State>({
password: '',
showPassword: false
})
// ** Hook
const theme = useTheme()
const router = useRouter()
const handleChange = (prop: keyof State) => (event: ChangeEvent<HTMLInputElement>) => {
setValues({ ...values, [prop]: event.target.value })
}
const handleClickShowPassword = () => {
setValues({ ...values, showPassword: !values.showPassword })
}
const handleMouseDownPassword = (event: MouseEvent<HTMLButtonElement>) => {
event.preventDefault()
}
return (
<Box className='content-center'>
<Card sx={{ zIndex: 1 }}>
<CardContent sx={{ padding: theme => `${theme.spacing(12, 9, 7)} !important` }}>
<Box sx={{ mb: 8, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<svg
width={35}
height={29}
version='1.1'
viewBox='0 0 30 23'
xmlns='http://www.w3.org/2000/svg'
xmlnsXlink='http://www.w3.org/1999/xlink'
>
<g stroke='none' strokeWidth='1' fill='none' fillRule='evenodd'>
<g id='Artboard' transform='translate(-95.000000, -51.000000)'>
<g id='logo' transform='translate(95.000000, 50.000000)'>
<path
id='Combined-Shape'
fill={theme.palette.primary.main}
d='M30,21.3918362 C30,21.7535219 29.9019196,22.1084381 29.7162004,22.4188007 C29.1490236,23.366632 27.9208668,23.6752135 26.9730355,23.1080366 L26.9730355,23.1080366 L23.714971,21.1584295 C23.1114106,20.7972624 22.7419355,20.1455972 22.7419355,19.4422291 L22.7419355,19.4422291 L22.741,12.7425689 L15,17.1774194 L7.258,12.7425689 L7.25806452,19.4422291 C7.25806452,20.1455972 6.88858935,20.7972624 6.28502902,21.1584295 L3.0269645,23.1080366 C2.07913318,23.6752135 0.850976404,23.366632 0.283799571,22.4188007 C0.0980803893,22.1084381 2.0190442e-15,21.7535219 0,21.3918362 L0,3.58469444 L0.00548573643,3.43543209 L0.00548573643,3.43543209 L0,3.5715689 C3.0881846e-16,2.4669994 0.8954305,1.5715689 2,1.5715689 C2.36889529,1.5715689 2.73060353,1.67359571 3.04512412,1.86636639 L15,9.19354839 L26.9548759,1.86636639 C27.2693965,1.67359571 27.6311047,1.5715689 28,1.5715689 C29.1045695,1.5715689 30,2.4669994 30,3.5715689 L30,3.5715689 Z'
/>
<polygon
id='Rectangle'
opacity='0.077704'
fill={theme.palette.common.black}
points='0 8.58870968 7.25806452 12.7505183 7.25806452 16.8305646'
/>
<polygon
id='Rectangle'
opacity='0.077704'
fill={theme.palette.common.black}
points='0 8.58870968 7.25806452 12.6445567 7.25806452 15.1370162'
/>
<polygon
id='Rectangle'
opacity='0.077704'
fill={theme.palette.common.black}
points='22.7419355 8.58870968 30 12.7417372 30 16.9537453'
transform='translate(26.370968, 12.771227) scale(-1, 1) translate(-26.370968, -12.771227) '
/>
<polygon
id='Rectangle'
opacity='0.077704'
fill={theme.palette.common.black}
points='22.7419355 8.58870968 30 12.6409734 30 15.2601969'
transform='translate(26.370968, 11.924453) scale(-1, 1) translate(-26.370968, -11.924453) '
/>
<path
id='Rectangle'
fillOpacity='0.15'
fill={theme.palette.common.white}
d='M3.04512412,1.86636639 L15,9.19354839 L15,9.19354839 L15,17.1774194 L0,8.58649679 L0,3.5715689 C3.0881846e-16,2.4669994 0.8954305,1.5715689 2,1.5715689 C2.36889529,1.5715689 2.73060353,1.67359571 3.04512412,1.86636639 Z'
/>
<path
id='Rectangle'
fillOpacity='0.35'
fill={theme.palette.common.white}
transform='translate(22.500000, 8.588710) scale(-1, 1) translate(-22.500000, -8.588710) '
d='M18.0451241,1.86636639 L30,9.19354839 L30,9.19354839 L30,17.1774194 L15,8.58649679 L15,3.5715689 C15,2.4669994 15.8954305,1.5715689 17,1.5715689 C17.3688953,1.5715689 17.7306035,1.67359571 18.0451241,1.86636639 Z'
/>
</g>
</g>
</g>
</svg>
<Typography
variant='h6'
sx={{
ml: 3,
lineHeight: 1,
fontWeight: 600,
textTransform: 'uppercase',
fontSize: '1.5rem !important'
}}
>
{themeConfig.templateName}
</Typography>
</Box>
<Box sx={{ mb: 6 }}>
<Typography variant='h5' sx={{ fontWeight: 600, marginBottom: 1.5 }}>
Welcome to {themeConfig.templateName}! 👋🏻
</Typography>
<Typography variant='body2'>Please sign-in to your account and start the adventure</Typography>
</Box>
<form noValidate autoComplete='off' onSubmit={e => e.preventDefault()}>
<TextField autoFocus fullWidth id='email' label='Email' sx={{ marginBottom: 4 }} />
<FormControl fullWidth>
<InputLabel htmlFor='auth-login-password'>Password</InputLabel>
<OutlinedInput
label='Password'
value={values.password}
id='auth-login-password'
onChange={handleChange('password')}
type={values.showPassword ? 'text' : 'password'}
endAdornment={
<InputAdornment position='end'>
<IconButton
edge='end'
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
aria-label='toggle password visibility'
>
{values.showPassword ? <EyeOutline /> : <EyeOffOutline />}
</IconButton>
</InputAdornment>
}
/>
</FormControl>
<Box
sx={{ mb: 4, display: 'flex', alignItems: 'center', flexWrap: 'wrap', justifyContent: 'space-between' }}
>
<FormControlLabel control={<Checkbox />} label='Remember Me' />
<Link passHref href='/'>
<LinkStyled onClick={e => e.preventDefault()}>Forgot Password?</LinkStyled>
</Link>
</Box>
<Button
fullWidth
size='large'
variant='contained'
sx={{ marginBottom: 7 }}
onClick={() => router.push('/')}
>
Login
</Button>
<Box sx={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', justifyContent: 'center' }}>
<Typography variant='body2' sx={{ marginRight: 2 }}>
New on our platform?
</Typography>
<Typography variant='body2'>
<Link passHref href='/pages/register'>
<LinkStyled>Create an account</LinkStyled>
</Link>
</Typography>
</Box>
<Divider sx={{ my: 5 }}>or</Divider>
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<Link href='/' passHref>
<IconButton component='a' onClick={(e: MouseEvent<HTMLElement>) => e.preventDefault()}>
<Facebook sx={{ color: '#497ce2' }} />
</IconButton>
</Link>
<Link href='/' passHref>
<IconButton component='a' onClick={(e: MouseEvent<HTMLElement>) => e.preventDefault()}>
<Twitter sx={{ color: '#1da1f2' }} />
</IconButton>
</Link>
<Link href='/' passHref>
<IconButton component='a' onClick={(e: MouseEvent<HTMLElement>) => e.preventDefault()}>
<Github
sx={{ color: theme => (theme.palette.mode === 'light' ? '#272727' : theme.palette.grey[300]) }}
/>
</IconButton>
</Link>
<Link href='/' passHref>
<IconButton component='a' onClick={(e: MouseEvent<HTMLElement>) => e.preventDefault()}>
<Google sx={{ color: '#db4437' }} />
</IconButton>
</Link>
</Box>
</form>
</CardContent>
</Card>
<FooterIllustrationsV1 />
</Box>
)
}
LoginPage.getLayout = (page: ReactNode) => <BlankLayout>{page}</BlankLayout>
export default LoginPage

View File

@ -1,255 +0,0 @@
// ** React Imports
import { useState, Fragment, ChangeEvent, MouseEvent, ReactNode } from 'react'
// ** Next Imports
import Link from 'next/link'
// ** MUI Components
import Box from '@mui/material/Box'
import Button from '@mui/material/Button'
import Divider from '@mui/material/Divider'
import Checkbox from '@mui/material/Checkbox'
import TextField from '@mui/material/TextField'
import Typography from '@mui/material/Typography'
import InputLabel from '@mui/material/InputLabel'
import IconButton from '@mui/material/IconButton'
import CardContent from '@mui/material/CardContent'
import FormControl from '@mui/material/FormControl'
import OutlinedInput from '@mui/material/OutlinedInput'
import { styled, useTheme } from '@mui/material/styles'
import MuiCard, { CardProps } from '@mui/material/Card'
import InputAdornment from '@mui/material/InputAdornment'
import MuiFormControlLabel, { FormControlLabelProps } from '@mui/material/FormControlLabel'
// ** Icons Imports
import Google from 'mdi-material-ui/Google'
import Github from 'mdi-material-ui/Github'
import Twitter from 'mdi-material-ui/Twitter'
import Facebook from 'mdi-material-ui/Facebook'
import EyeOutline from 'mdi-material-ui/EyeOutline'
import EyeOffOutline from 'mdi-material-ui/EyeOffOutline'
// ** Configs
import themeConfig from '../configs/themeConfig'
// ** Layout Import
import BlankLayout from '../core/layouts/BlankLayout'
// ** Demo Imports
import FooterIllustrationsV1 from '../views/pages/auth/FooterIllustration'
interface State {
password: string
showPassword: boolean
}
// ** Styled Components
const Card = styled(MuiCard)<CardProps>(({ theme }) => ({
[theme.breakpoints.up('sm')]: { width: '28rem' }
}))
const LinkStyled = styled('a')(({ theme }) => ({
fontSize: '0.875rem',
textDecoration: 'none',
color: theme.palette.primary.main
}))
const FormControlLabel = styled(MuiFormControlLabel)<FormControlLabelProps>(({ theme }) => ({
marginTop: theme.spacing(1.5),
marginBottom: theme.spacing(4),
'& .MuiFormControlLabel-label': {
fontSize: '0.875rem',
color: theme.palette.text.secondary
}
}))
const RegisterPage = () => {
// ** States
const [values, setValues] = useState<State>({
password: '',
showPassword: false
})
// ** Hook
const theme = useTheme()
const handleChange = (prop: keyof State) => (event: ChangeEvent<HTMLInputElement>) => {
setValues({ ...values, [prop]: event.target.value })
}
const handleClickShowPassword = () => {
setValues({ ...values, showPassword: !values.showPassword })
}
const handleMouseDownPassword = (event: MouseEvent<HTMLButtonElement>) => {
event.preventDefault()
}
return (
<Box className='content-center'>
<Card sx={{ zIndex: 1 }}>
<CardContent sx={{ padding: theme => `${theme.spacing(12, 9, 7)} !important` }}>
<Box sx={{ mb: 8, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<svg
width={35}
height={29}
version='1.1'
viewBox='0 0 30 23'
xmlns='http://www.w3.org/2000/svg'
xmlnsXlink='http://www.w3.org/1999/xlink'
>
<g stroke='none' strokeWidth='1' fill='none' fillRule='evenodd'>
<g id='Artboard' transform='translate(-95.000000, -51.000000)'>
<g id='logo' transform='translate(95.000000, 50.000000)'>
<path
id='Combined-Shape'
fill={theme.palette.primary.main}
d='M30,21.3918362 C30,21.7535219 29.9019196,22.1084381 29.7162004,22.4188007 C29.1490236,23.366632 27.9208668,23.6752135 26.9730355,23.1080366 L26.9730355,23.1080366 L23.714971,21.1584295 C23.1114106,20.7972624 22.7419355,20.1455972 22.7419355,19.4422291 L22.7419355,19.4422291 L22.741,12.7425689 L15,17.1774194 L7.258,12.7425689 L7.25806452,19.4422291 C7.25806452,20.1455972 6.88858935,20.7972624 6.28502902,21.1584295 L3.0269645,23.1080366 C2.07913318,23.6752135 0.850976404,23.366632 0.283799571,22.4188007 C0.0980803893,22.1084381 2.0190442e-15,21.7535219 0,21.3918362 L0,3.58469444 L0.00548573643,3.43543209 L0.00548573643,3.43543209 L0,3.5715689 C3.0881846e-16,2.4669994 0.8954305,1.5715689 2,1.5715689 C2.36889529,1.5715689 2.73060353,1.67359571 3.04512412,1.86636639 L15,9.19354839 L26.9548759,1.86636639 C27.2693965,1.67359571 27.6311047,1.5715689 28,1.5715689 C29.1045695,1.5715689 30,2.4669994 30,3.5715689 L30,3.5715689 Z'
/>
<polygon
id='Rectangle'
opacity='0.077704'
fill={theme.palette.common.black}
points='0 8.58870968 7.25806452 12.7505183 7.25806452 16.8305646'
/>
<polygon
id='Rectangle'
opacity='0.077704'
fill={theme.palette.common.black}
points='0 8.58870968 7.25806452 12.6445567 7.25806452 15.1370162'
/>
<polygon
id='Rectangle'
opacity='0.077704'
fill={theme.palette.common.black}
points='22.7419355 8.58870968 30 12.7417372 30 16.9537453'
transform='translate(26.370968, 12.771227) scale(-1, 1) translate(-26.370968, -12.771227) '
/>
<polygon
id='Rectangle'
opacity='0.077704'
fill={theme.palette.common.black}
points='22.7419355 8.58870968 30 12.6409734 30 15.2601969'
transform='translate(26.370968, 11.924453) scale(-1, 1) translate(-26.370968, -11.924453) '
/>
<path
id='Rectangle'
fillOpacity='0.15'
fill={theme.palette.common.white}
d='M3.04512412,1.86636639 L15,9.19354839 L15,9.19354839 L15,17.1774194 L0,8.58649679 L0,3.5715689 C3.0881846e-16,2.4669994 0.8954305,1.5715689 2,1.5715689 C2.36889529,1.5715689 2.73060353,1.67359571 3.04512412,1.86636639 Z'
/>
<path
id='Rectangle'
fillOpacity='0.35'
fill={theme.palette.common.white}
transform='translate(22.500000, 8.588710) scale(-1, 1) translate(-22.500000, -8.588710) '
d='M18.0451241,1.86636639 L30,9.19354839 L30,9.19354839 L30,17.1774194 L15,8.58649679 L15,3.5715689 C15,2.4669994 15.8954305,1.5715689 17,1.5715689 C17.3688953,1.5715689 17.7306035,1.67359571 18.0451241,1.86636639 Z'
/>
</g>
</g>
</g>
</svg>
<Typography
variant='h6'
sx={{
ml: 3,
lineHeight: 1,
fontWeight: 600,
textTransform: 'uppercase',
fontSize: '1.5rem !important'
}}
>
{themeConfig.templateName}
</Typography>
</Box>
<Box sx={{ mb: 6 }}>
<Typography variant='h5' sx={{ fontWeight: 600, marginBottom: 1.5 }}>
Adventure starts here 🚀
</Typography>
<Typography variant='body2'>Make your app management easy and fun!</Typography>
</Box>
<form noValidate autoComplete='off' onSubmit={e => e.preventDefault()}>
<TextField autoFocus fullWidth id='username' label='Username' sx={{ marginBottom: 4 }} />
<TextField fullWidth type='email' label='Email' sx={{ marginBottom: 4 }} />
<FormControl fullWidth>
<InputLabel htmlFor='auth-register-password'>Password</InputLabel>
<OutlinedInput
label='Password'
value={values.password}
id='auth-register-password'
onChange={handleChange('password')}
type={values.showPassword ? 'text' : 'password'}
endAdornment={
<InputAdornment position='end'>
<IconButton
edge='end'
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
aria-label='toggle password visibility'
>
{values.showPassword ? <EyeOutline fontSize='small' /> : <EyeOffOutline fontSize='small' />}
</IconButton>
</InputAdornment>
}
/>
</FormControl>
<FormControlLabel
control={<Checkbox />}
label={
<Fragment>
<span>I agree to </span>
<Link href='/' passHref>
<LinkStyled onClick={(e: MouseEvent<HTMLElement>) => e.preventDefault()}>
privacy policy & terms
</LinkStyled>
</Link>
</Fragment>
}
/>
<Button fullWidth size='large' type='submit' variant='contained' sx={{ marginBottom: 7 }}>
Sign up
</Button>
<Box sx={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', justifyContent: 'center' }}>
<Typography variant='body2' sx={{ marginRight: 2 }}>
Already have an account?
</Typography>
<Typography variant='body2'>
<Link passHref href='/pages/login'>
<LinkStyled>Sign in instead</LinkStyled>
</Link>
</Typography>
</Box>
<Divider sx={{ my: 5 }}>or</Divider>
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<Link href='/' passHref>
<IconButton component='a' onClick={(e: MouseEvent<HTMLElement>) => e.preventDefault()}>
<Facebook sx={{ color: '#497ce2' }} />
</IconButton>
</Link>
<Link href='/' passHref>
<IconButton component='a' onClick={(e: MouseEvent<HTMLElement>) => e.preventDefault()}>
<Twitter sx={{ color: '#1da1f2' }} />
</IconButton>
</Link>
<Link href='/' passHref>
<IconButton component='a' onClick={(e: MouseEvent<HTMLElement>) => e.preventDefault()}>
<Github
sx={{ color: theme => (theme.palette.mode === 'light' ? '#272727' : theme.palette.grey[300]) }}
/>
</IconButton>
</Link>
<Link href='/' passHref>
<IconButton component='a' onClick={(e: MouseEvent<HTMLElement>) => e.preventDefault()}>
<Google sx={{ color: '#db4437' }} />
</IconButton>
</Link>
</Box>
</form>
</CardContent>
</Card>
<FooterIllustrationsV1 />
</Box>
)
}
RegisterPage.getLayout = (page: ReactNode) => <BlankLayout>{page}</BlankLayout>
export default RegisterPage

View File

@ -1,67 +0,0 @@
// ** MUI Imports
import Grid from '@mui/material/Grid'
import Link from '@mui/material/Link'
import Card from '@mui/material/Card'
import Typography from '@mui/material/Typography'
import CardHeader from '@mui/material/CardHeader'
// ** Demo Components Imports
import TableBasic from '../views/tables/TableBasic'
import TableDense from '../views/tables/TableDense'
import TableSpanning from '../views/tables/TableSpanning'
import TableCustomized from '../views/tables/TableCustomized'
import TableCollapsible from '../views/tables/TableCollapsible'
import TableStickyHeader from '../views/tables/TableStickyHeader'
const MUITable = () => {
return (
<Grid container spacing={6}>
<Grid item xs={12}>
<Typography variant='h5'>
<Link href='https://mui.com/components/tables/' target='_blank'>
MUI Tables
</Link>
</Typography>
<Typography variant='body2'>Tables display sets of data. They can be fully customized</Typography>
</Grid>
<Grid item xs={12}>
<Card>
<CardHeader title='Basic Table' titleTypographyProps={{ variant: 'h6' }} />
<TableBasic />
</Card>
</Grid>
<Grid item xs={12}>
<Card>
<CardHeader title='Dense Table' titleTypographyProps={{ variant: 'h6' }} />
<TableDense />
</Card>
</Grid>
<Grid item xs={12}>
<Card>
<CardHeader title='Sticky Header' titleTypographyProps={{ variant: 'h6' }} />
<TableStickyHeader />
</Card>
</Grid>
<Grid item xs={12}>
<Card>
<CardHeader title='Collapsible Table' titleTypographyProps={{ variant: 'h6' }} />
<TableCollapsible />
</Card>
</Grid>
<Grid item xs={12}>
<Card>
<CardHeader title='Spanning Table' titleTypographyProps={{ variant: 'h6' }} />
<TableSpanning />
</Card>
</Grid>
<Grid item xs={12}>
<Card>
<CardHeader title='Customized Table' titleTypographyProps={{ variant: 'h6' }} />
<TableCustomized />
</Card>
</Grid>
</Grid>
)
}
export default MUITable

View File

@ -1,21 +0,0 @@
// ** MUI Imports
import Grid from '@mui/material/Grid'
// ** Demo Components Imports
import TypographyTexts from '../views/typography/TypographyTexts'
import TypographyHeadings from '../views/typography/TypographyHeadings'
const TypographyPage = () => {
return (
<Grid container spacing={6}>
<Grid item xs={12}>
<TypographyHeadings />
</Grid>
<Grid item xs={12}>
<TypographyTexts />
</Grid>
</Grid>
)
}
export default TypographyPage