-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Convert to a Next + Redux app #35
base: main
Are you sure you want to change the base?
Changes from 1 commit
8f53cc6
45caf00
8bebc35
2442df1
4ae4e75
29e3224
3808032
464a4ca
100c92c
0f149fa
e06e179
0442475
cdc449a
6f12bc4
aa52a6e
cdffcf5
e63b5fa
d38e44a
2dc5028
2eeb2c3
0348cec
523935c
a5b3359
c116824
222a655
9c04937
b7db8bc
4235baf
cf6a269
79f1368
578792f
d8359b3
3d6c19c
659385b
1375ec1
6d7c99d
7fb80e0
4b3324b
1105b25
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,151 @@ | ||
import AdminGuard from "@/app/components/Admin/AdminGuard"; | ||
'use client'; | ||
import React, { useEffect, useState } from "react"; | ||
import { Box, Button, ColorPaletteProp, Link, Tab, TabList, TabPanel, Tabs, Typography } from "@mui/joy"; | ||
import { tabClasses } from "@mui/joy"; | ||
import OpenInNewIcon from '@mui/icons-material/OpenInNew'; | ||
import { toast } from "sonner"; | ||
import { getAuthenticatedUser, useSelector } from "@/lib/redux"; | ||
|
||
/** | ||
* Depicts the station management page from a station manager perspective. | ||
* @page | ||
* @category Station Management | ||
* | ||
* @param {Object} props - The component props. | ||
* @param {string} [props.style] - The style of the page. Defaults to the success color. | ||
* | ||
* @returns {JSX.Element} The rendered StationManagementPage component. | ||
* @example | ||
* return ( | ||
* <StationManagementPage /> | ||
* ) | ||
*/ | ||
const StationManagementPage = (props: { style: ColorPaletteProp }) => { | ||
|
||
const user = useSelector(getAuthenticatedUser); | ||
|
||
const [djs, setDjs] = useState([]); | ||
const [loading, setLoading] = useState(true); | ||
|
||
const updateDjs = async () => { | ||
setLoading(true); | ||
listUsers().then((data: any) => { | ||
setDjs(data); | ||
setLoading(false); | ||
}); | ||
}; | ||
|
||
useEffect(() => { | ||
updateDjs(); | ||
}, []); | ||
|
||
const AdminPage = () => { | ||
return ( | ||
<div> | ||
<AdminGuard /> | ||
<h1>Admin Page</h1> | ||
</div> | ||
<> | ||
<Box | ||
sx={{ | ||
display: 'flex', | ||
alignItems: 'center', | ||
justifyContent: 'flex-end', | ||
my: 1, | ||
gap: 1, | ||
flexWrap: 'wrap', | ||
'& > *': { | ||
minWidth: 'clamp(0px, (500px - 100%) * 999, 100%)', | ||
flexGrow: 1, | ||
}, | ||
}} | ||
> | ||
<Typography level="h1"> | ||
Station Management | ||
</Typography> | ||
<Box sx = {{ justifyContent: 'flex-end', display: 'flex' }}> | ||
<Link | ||
href="https://wxyc.awsapps.com/start#/" | ||
target="_blank" | ||
sx = {{ | ||
'&:hover': { | ||
textDecoration: 'none', | ||
}, | ||
}} | ||
> | ||
<Button variant="outlined" color={props.style ?? 'success'} endDecorator={<OpenInNewIcon fontSize="small" />} >AWS Management Console</Button> | ||
</Link> | ||
</Box> | ||
</Box> | ||
<Tabs | ||
size="sm" | ||
aria-label="Station Management Tabs" | ||
defaultValue={0} | ||
color={props.style ?? 'success'} | ||
sx = {(theme) => ({ | ||
'--Tabs-gap': '0px', | ||
borderRadius: 'lg', | ||
border: `1px solid ${theme.palette.divider}`, | ||
width: '100%', | ||
flex: 1, | ||
|
||
|
||
position: 'relative', | ||
})} | ||
> | ||
<TabList | ||
sx={{ | ||
'--ListItem-radius': '0px', | ||
borderRadius: 0, | ||
[`& .${tabClasses.root}`]: { | ||
fontWeight: 'md', | ||
flex: 1, | ||
bgcolor: 'background.body', | ||
[`&.${tabClasses.selected}`]: { | ||
color: `${props.style ?? 'success'}.500`, | ||
}, | ||
[`&.${tabClasses.selected}:before`]: { | ||
content: '""', | ||
display: 'block', | ||
position: 'absolute', | ||
bottom: -1, | ||
width: '100%', | ||
height: 2, | ||
bgcolor: `${props.style ?? 'success'}.400`, | ||
}, | ||
[`&.${tabClasses.focusVisible}`]: { | ||
outlineOffset: '-3px', | ||
}, | ||
}, | ||
}} | ||
> | ||
<Tab sx = {{ py: 1.5 }}>Roster</Tab> | ||
<Tab sx = {{ py: 1.5 }}>Schedule</Tab> | ||
<Tab sx = {{ py: 1.5 }}>Rotation</Tab> | ||
<Tab sx = {{ py: 1.5 }}>Catalog</Tab> | ||
</TabList> | ||
<TabPanel value={0}> | ||
<DJRoster | ||
roster={djs} | ||
updateDjs={updateDjs} | ||
setDjs={setDjs} | ||
loading={loading} | ||
setLoading={setLoading} | ||
/> | ||
</TabPanel> | ||
<TabPanel value={1} | ||
sx = {{ | ||
flex: '0 1 auto', | ||
}} | ||
> | ||
<StationSchedule | ||
roster={djs} | ||
/> | ||
</TabPanel> | ||
<TabPanel value={2}> | ||
<RotationManagement /> | ||
</TabPanel> | ||
<TabPanel value={3}> | ||
<CatalogEditor /> | ||
</TabPanel> | ||
</Tabs> | ||
</> | ||
); | ||
}; | ||
} | ||
|
||
export default AdminPage; | ||
export default StationManagementPage; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,26 @@ | ||
'use client'; | ||
|
||
import { getAuthenticatedUser, useSelector } from "@/lib/redux"; | ||
import { fetchDJs, getAuthenticatedUser, useDispatch, useSelector } from "@/lib/redux"; | ||
import { getter } from "@/lib/services"; | ||
import { useEffect } from "react"; | ||
import { toast } from "sonner"; | ||
|
||
export default function VerifyPage() { | ||
|
||
const user = useSelector(getAuthenticatedUser); | ||
const dispatch = useDispatch(); | ||
|
||
useEffect(() => { | ||
console.log("mounted"); | ||
|
||
const process = async (e: KeyboardEvent) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you rename this to something more descriptive like |
||
if ((e as KeyboardEvent).key === 'v') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you leave a comment that documents why |
||
const { data, error } = await getter('testAuth')(); | ||
|
||
if (error) { | ||
console.error(error); | ||
toast.error(error.message); | ||
} else { | ||
console.table(data); | ||
toast.success(data.message); | ||
let token = sessionStorage.getItem("idToken"); | ||
if (!token) { | ||
toast.error("No TOKEN!!!"); | ||
return; | ||
} | ||
await dispatch(fetchDJs(token)); | ||
} | ||
} | ||
|
||
|
@@ -30,9 +30,7 @@ export default function VerifyPage() { | |
console.log('Verify page unmounted'); | ||
window.removeEventListener('keydown', process); | ||
} | ||
}, []); | ||
|
||
const user = useSelector(getAuthenticatedUser); | ||
}, [user?.djId]); | ||
|
||
return ( | ||
<> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export * from "./types"; | ||
export * from "./slice"; | ||
export * from "./thunks"; | ||
export * from "./selectors"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/* Instruments */ | ||
import { type ReduxState } from "@/lib/redux"; | ||
|
||
|
||
const getAdminLoading = (state: ReduxState) => state.admin.loading; | ||
const getDJs = (state: ReduxState) => state.admin.djs; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { createSlice } from "@reduxjs/toolkit"; | ||
import { AdminState } from "./types"; | ||
|
||
const initialState: AdminState = { | ||
loading: false, | ||
djs: [], | ||
}; | ||
|
||
export const adminSlice = createSlice({ | ||
name: "admin", | ||
initialState, | ||
reducers: { | ||
|
||
} | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { CognitoIdentityProviderClient, ListUsersCommand, ListUsersCommandInput } from "@aws-sdk/client-cognito-identity-provider"; | ||
import { createAppAsyncThunk } from "../../createAppAsyncThunk"; | ||
import { User } from "../authentication"; | ||
import { getCredentials } from "../.."; | ||
|
||
export const fetchDJs = createAppAsyncThunk( | ||
"admin/fetchDJs", | ||
async (idToken: string): Promise<boolean> => { | ||
|
||
const client = new CognitoIdentityProviderClient({ | ||
credentials: await getCredentials(idToken), | ||
region: process.env.NEXT_PUBLIC_AWS_REGION | ||
}); | ||
|
||
const params: ListUsersCommandInput = { | ||
UserPoolId: process.env.NEXT_PUBLIC_USER_POOL_ID, | ||
AttributesToGet: [ | ||
"email", | ||
"name", | ||
"custom:dj-name", | ||
] | ||
}; | ||
|
||
const listCommand = new ListUsersCommand(params); | ||
const listResponse = await client.send(listCommand); | ||
|
||
console.table(listResponse); | ||
console.table(listResponse.Users); | ||
|
||
return true; | ||
} | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
|
||
export interface AdminState { | ||
loading: boolean; | ||
djs: DJ[]; | ||
}; | ||
|
||
export interface DJ { | ||
id: number; | ||
real_name: string; | ||
dj_name: string; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you fix the indentation, please?