web: fix up
All checks were successful
continuous-integration/drone/push Build is passing

When possible you should not use inline styling and instead use SCSS files for following convention and keeping consistency, Grid is also a deprecated React component in Material UI
You should also separate components that are client only to its own .tsx module rather than having it be mixed with components that aren't required for being client only
This commit is contained in:
rhpidfyre 2024-12-19 02:24:38 -05:00
parent b0b16c91dc
commit a7e9dbb94d
7 changed files with 77 additions and 66 deletions

View File

@ -11,9 +11,14 @@
position: relative; position: relative;
} }
a { color:rgb(255, 255, 255) } a {
color:rgb(255, 255, 255);
a:visited { text-decoration: none; color:rgb(255, 255, 255); } &:visited, &:hover, &:focus {
a:hover { text-decoration: none; color:rgb(255, 255, 255); } text-decoration: none;
a:focus { text-decoration: none; color:rgb(255, 255, 255); } color: rgb(255, 255, 255);
a:hover, a:active { text-decoration: none; color:rgb(192, 192, 192) } }
&:active {
color: rgb(192, 192, 192)
}
}

View File

@ -1,16 +1,18 @@
import { Button, ButtonOwnProps } from "@mui/material"; import { Button, ButtonOwnProps } from "@mui/material";
import { SubmissionInfo } from "@/app/ts/Submission"; import { SubmissionInfo } from "@/app/ts/Submission";
type Review = "Completed" | "Submit" | "Reject" | "Revoke" | "Accept" | "Validate" | "Upload" type Actions = "Completed" | "Submit" | "Reject" | "Revoke"
type Action = "completed" | "submit" | "reject" | "revoke" | "trigger-validate" | "trigger-upload" type Review = Actions | "Accept" | "Validate" | "Upload"
type Action = Lowercase<Actions> | "trigger-validate" | "trigger-upload"
interface ReviewButton { interface ReviewButton {
name: Review, name: Review,
action: Action, action: Action,
submissionId: number, submissionId: string,
color: ButtonOwnProps["color"] color: ButtonOwnProps["color"]
} }
function ReviewButtonClicked(action: Action, submissionId: number) { function ReviewButtonClicked(action: Action, submissionId: string) {
fetch(`/api/submissions/${submissionId}/status/${action}`, { fetch(`/api/submissions/${submissionId}/status/${action}`, {
method: "POST", method: "POST",
headers: { headers: {
@ -27,15 +29,17 @@ function ReviewButton(props: ReviewButton) {
} }
export default function ReviewButtons(props: SubmissionInfo) { export default function ReviewButtons(props: SubmissionInfo) {
const submissionId = props.ID.toString()
return ( return (
<section className="review-set"> <section className="review-set">
<ReviewButton color="info" name="Submit" action="submit" submissionId={props.ID}/> <ReviewButton color="info" name="Submit" action="submit" submissionId={submissionId}/>
<ReviewButton color="info" name="Revoke" action="revoke" submissionId={props.ID}/> <ReviewButton color="info" name="Revoke" action="revoke" submissionId={submissionId}/>
<ReviewButton color="info" name="Accept" action="trigger-validate" submissionId={props.ID}/> <ReviewButton color="info" name="Accept" action="trigger-validate" submissionId={submissionId}/>
<ReviewButton color="info" name="Validate" action="trigger-validate" submissionId={props.ID}/> <ReviewButton color="info" name="Validate" action="trigger-validate" submissionId={submissionId}/>
<ReviewButton color="error" name="Reject" action="reject" submissionId={props.ID}/> <ReviewButton color="error" name="Reject" action="reject" submissionId={submissionId}/>
<ReviewButton color="info" name="Upload" action="trigger-upload" submissionId={props.ID}/> <ReviewButton color="info" name="Upload" action="trigger-upload" submissionId={submissionId}/>
<ReviewButton color="info" name="Completed" action="completed" submissionId={props.ID}/> <ReviewButton color="info" name="Completed" action="completed" submissionId={submissionId}/>
</section> </section>
) )
} }

View File

@ -75,18 +75,18 @@ export default function SubmissionInfoPage() {
useEffect(() => { // needs to be client sided since server doesn't have a session, nextjs got mad at me for exporting an async function: (https://nextjs.org/docs/messages/no-async-client-component) useEffect(() => { // needs to be client sided since server doesn't have a session, nextjs got mad at me for exporting an async function: (https://nextjs.org/docs/messages/no-async-client-component)
async function getSubmission() { async function getSubmission() {
const res = await fetch(`/api/submissions/${dynamicId.submissionId}`) const res = await fetch(`/api/submissions/${dynamicId.submissionId}`)
const data = await res.json() if (res.ok) {
setSubmission(data) setSubmission(await res.json())
}
} }
getSubmission() getSubmission()
}, [dynamicId.submissionId]) }, [dynamicId.submissionId])
if (!submission) return ( if (!submission) {
<Webpage> return <Webpage>
{/* TODO: Add skeleton loading thingy ? Maybe ? (https://mui.com/material-ui/react-skeleton/) */} {/* TODO: Add skeleton loading thingy ? Maybe ? (https://mui.com/material-ui/react-skeleton/) */}
</Webpage> </Webpage>
) }
return ( return (
<Webpage> <Webpage>
<main className="map-page-main"> <main className="map-page-main">

View File

@ -3,22 +3,22 @@ import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
interface SubmissionCardProps { interface SubmissionCardProps {
id: number;
assetId: number;
displayName: string; displayName: string;
author: string; assetId: number;
rating: number; rating: number;
author: string;
id: number;
} }
export default function SubmissionCard({ id, displayName, author, rating }: SubmissionCardProps) { export default function SubmissionCard(props: SubmissionCardProps) {
return ( return (
<Link href={`/submissions/${id}`}> <Link href={`/submissions/${props.id}`}>
<div className="submissionCard"> <div className="submissionCard">
{/* TODO: Grab image of model */} {/* TODO: Grab image of model */}
<Image height={200} width={200} priority={true} src="https://api.ic3.space/strafe/map-images/11222350808" style={{ width: `100%` }} alt={displayName} /> <Image height={200} width={200} priority={true} src="https://api.ic3.space/strafe/map-images/11222350808" style={{ width: `100%` }} alt={props.displayName} />
<h3>{displayName}</h3> <h3>{props.displayName}</h3>
<p>By {author}</p> <p>By {props.author}</p>
<p> {rating}</p> {/* TODO: paste the star element from submission/1 page */} <p> {props.rating}</p> {/* TODO: paste the star element from submission/1 page */}
</div> </div>
</Link> </Link>
); );

View File

@ -1,22 +1,25 @@
//This can all be solved using 0 JavaScript,
//display: grid, ->1fr unit<-
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Grid, Skeleton } from '@mui/material'; import { Grid, Skeleton } from '@mui/material';
const SkeletonGrid = () => { const elementWidth = 220;
function calculateSkeletonCount(setState: React.Dispatch<React.SetStateAction<number>>) {
const viewportWidth = window.innerWidth - 100 * 2;
setState(Math.floor(viewportWidth / elementWidth) * 2);
};
function SkeletonGrid() {
const [skeletonCount, setSkeletonCount] = useState(0); const [skeletonCount, setSkeletonCount] = useState(0);
const calculateSkeletonCount = () => {
const viewportWidth = window.innerWidth - 100 * 2;
const elementWidth = 220;
const count = Math.floor(viewportWidth / elementWidth);
setSkeletonCount(count * 2);
};
useEffect(() => { useEffect(() => {
calculateSkeletonCount(); calculateSkeletonCount(setSkeletonCount);
window.addEventListener('resize', calculateSkeletonCount); window.addEventListener('resize', () => { calculateSkeletonCount(setSkeletonCount) });
return () => { return () => {
window.removeEventListener('resize', calculateSkeletonCount); window.removeEventListener('resize', () => { calculateSkeletonCount(setSkeletonCount) });
}; };
}, []); }, []);

View File

@ -1,18 +1,16 @@
interface WindowStruct { interface WindowStruct {
children: React.ReactNode,
className: string, className: string,
title: string, title: string,
children: React.ReactNode
} }
export default function Window(window: WindowStruct) { export default function Window(window: WindowStruct) {
return ( return <section className={window.className}>
<section className={window.className}> <header>
<header> <p>{window.title}</p>
<p>{window.title}</p> </header>
</header> <main>{window.children}</main>
<main>{window.children}</main> </section>
</section>
)
} }
export { export {

View File

@ -1,13 +1,13 @@
'use client' 'use client'
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import Webpage from "@/app/_components/webpage"; import { SubmissionInfo } from '../ts/Submission';
import { Grid2 as Grid } from '@mui/material'; import { Grid2 as Grid } from '@mui/material';
import SubmissionCard from "./_card"; import SubmissionCard from "./_card";
import SkeletonGrid from './_loading'; import SkeletonGrid from './_loading';
import Webpage from "@/app/_components/webpage";
import "./(styles)/page.scss"; import "./(styles)/page.scss";
import { SubmissionInfo } from '../ts/Submission';
export default function SubmissionInfoPage() { export default function SubmissionInfoPage() {
const [submissions, setSubmissions] = useState<SubmissionInfo[]>([]) const [submissions, setSubmissions] = useState<SubmissionInfo[]>([])
@ -15,21 +15,22 @@ export default function SubmissionInfoPage() {
useEffect(() => { // needs to be client sided since server doesn't have a session, nextjs got mad at me for exporting an async function: (https://nextjs.org/docs/messages/no-async-client-component) useEffect(() => { // needs to be client sided since server doesn't have a session, nextjs got mad at me for exporting an async function: (https://nextjs.org/docs/messages/no-async-client-component)
async function fetchSubmissions() { async function fetchSubmissions() {
const res = await fetch('/api/submissions?Page=1&Limit=100') const res = await fetch('/api/submissions?Page=1&Limit=100')
const data = await res.json() if (res.ok) {
setSubmissions(data) setSubmissions(await res.json())
}
} }
setTimeout(() => { // testing loading screen made by chatGerbertPT setTimeout(() => { // testing loading screen made by chatGerbertPT
fetchSubmissions() fetchSubmissions()
}, 250); }, 250);
}, []) }, [])
if (!submissions) return ( if (!submissions) {
<Webpage> return <Webpage>
<main style={{ display: 'flex', justifyContent: 'center', padding: '1rem' }}> <main style={{ display: 'flex', justifyContent: 'center', padding: '1rem' }}>
<SkeletonGrid /> <SkeletonGrid />
</main> </main>
</Webpage> </Webpage>
) }
return ( return (
// TODO: Add filter settings & searchbar & page selector // TODO: Add filter settings & searchbar & page selector