This commit is contained in:
parent
02d77ab421
commit
9bd3eb69f9
@ -6,11 +6,24 @@ const nextConfig: NextConfig = {
|
|||||||
rewrites: async () => {
|
rewrites: async () => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
source: "/v1/submissions/:submissionid/status/:statustype",
|
source: "/api/:path*",
|
||||||
destination: "http://submissions:8082/v1/submissions/:submissionid/status/:statustype"
|
destination: "http://localhost:8082/v1/:path*",
|
||||||
|
// source: "/v1/submissions/:submissionid/status/:statustype",
|
||||||
|
// destination: "http://submissions:8082/v1/submissions/:submissionid/status/:statustype"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
images: {
|
||||||
|
remotePatterns: [
|
||||||
|
{
|
||||||
|
protocol: 'https',
|
||||||
|
hostname: 'api.ic3.space',
|
||||||
|
pathname: '/strafe/map-images/**',
|
||||||
|
port: '',
|
||||||
|
search: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
@ -18,10 +18,10 @@ export default function Header() {
|
|||||||
return (
|
return (
|
||||||
<header className="header-bar">
|
<header className="header-bar">
|
||||||
<nav className="left">
|
<nav className="left">
|
||||||
<HeaderButton name="Maps" href=""/>
|
<HeaderButton name="Submissions" href="/submissions"/>
|
||||||
</nav>
|
</nav>
|
||||||
<nav className="right">
|
<nav className="right">
|
||||||
<HeaderButton name="Home" href=""/>
|
<HeaderButton name="Submit" href="/submit"/>
|
||||||
<HeaderButton name="Need" href=""/>
|
<HeaderButton name="Need" href=""/>
|
||||||
<HeaderButton name="Menu" href=""/>
|
<HeaderButton name="Menu" href=""/>
|
||||||
<HeaderButton name="Items" href=""/>
|
<HeaderButton name="Items" href=""/>
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 100vw;
|
width: 100%;
|
||||||
height: 60px;
|
height: var(--header-height);
|
||||||
background: var(--header-grad-left);
|
background: var(--header-grad-left);
|
||||||
background: linear-gradient(180deg, var(--header-grad-left) 0%, var(--header-grad-right) 100%);
|
background: linear-gradient(180deg, var(--header-grad-left) 0%, var(--header-grad-right) 100%);
|
||||||
|
|
||||||
@ -24,7 +24,7 @@
|
|||||||
.right {
|
.right {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 7px;
|
gap: 7px;
|
||||||
margin-right: 50px;
|
margin-right: 35px;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
|
@ -10,6 +10,8 @@ $form-label-fontsize: 1.3rem;
|
|||||||
:root {
|
:root {
|
||||||
color-scheme: light dark;
|
color-scheme: light dark;
|
||||||
|
|
||||||
|
--header-height: 60px;
|
||||||
|
|
||||||
--page: white;
|
--page: white;
|
||||||
--header-grad-left: #363b40;
|
--header-grad-left: #363b40;
|
||||||
--header-grad-right: #353a40;
|
--header-grad-right: #353a40;
|
||||||
|
19
web/src/app/submissions/(styles)/page.scss
Normal file
19
web/src/app/submissions/(styles)/page.scss
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
@forward "./page/card.scss";
|
||||||
|
|
||||||
|
@use "../../globals.scss";
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: calc(100vh - var(--header-height));
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
a { color:rgb(255, 255, 255) }
|
||||||
|
|
||||||
|
a:visited { text-decoration: none; color:rgb(255, 255, 255); }
|
||||||
|
a:hover { text-decoration: none; color:rgb(255, 255, 255); }
|
||||||
|
a:focus { text-decoration: none; color:rgb(255, 255, 255); }
|
||||||
|
a:hover, a:active { text-decoration: none; color:rgb(192, 192, 192) }
|
12
web/src/app/submissions/(styles)/page/card.scss
Normal file
12
web/src/app/submissions/(styles)/page/card.scss
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
@use "../../../globals.scss";
|
||||||
|
|
||||||
|
.submissionCard {
|
||||||
|
@include globals.border-with-radius;
|
||||||
|
|
||||||
|
background-color: #2020207c;
|
||||||
|
border: 1px solid #501717;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 6px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import { Button, ButtonOwnProps } from "@mui/material";
|
import { Button, ButtonOwnProps } from "@mui/material";
|
||||||
|
import { SubmissionInfo } from "@/app/ts/Submission";
|
||||||
|
|
||||||
type Review = "Completed" | "Submit" | "Reject" | "Revoke" | "Accept" | "Validate" | "Upload"
|
type Review = "Completed" | "Submit" | "Reject" | "Revoke" | "Accept" | "Validate" | "Upload"
|
||||||
type Action = "completed" | "submit" | "reject" | "revoke" | "trigger-validate" | "trigger-upload"
|
type Action = "completed" | "submit" | "reject" | "revoke" | "trigger-validate" | "trigger-upload"
|
||||||
@ -9,12 +10,8 @@ interface ReviewButton {
|
|||||||
color: ButtonOwnProps["color"]
|
color: ButtonOwnProps["color"]
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ReviewId {
|
|
||||||
submissionId: string
|
|
||||||
}
|
|
||||||
|
|
||||||
function ReviewButtonClicked(action: Action, submissionId: string) {
|
function ReviewButtonClicked(action: Action, submissionId: string) {
|
||||||
fetch(`http://localhost:3000/v1/submissions/${submissionId}/status/${action}`, {
|
fetch(`/api/submissions/${submissionId}/status/${action}`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-type": "application/json",
|
"Content-type": "application/json",
|
||||||
@ -29,16 +26,16 @@ function ReviewButton(props: ReviewButton) {
|
|||||||
onClick={() => { ReviewButtonClicked(props.action, props.submissionId) }}>{props.name}</Button>
|
onClick={() => { ReviewButtonClicked(props.action, props.submissionId) }}>{props.name}</Button>
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ReviewButtons(props: ReviewId) {
|
export default function ReviewButtons(props: SubmissionInfo) {
|
||||||
return (
|
return (
|
||||||
<section className="review-set">
|
<section className="review-set">
|
||||||
<ReviewButton color="info" name="Submit" action="submit" submissionId={props.submissionId}/>
|
<ReviewButton color="info" name="Submit" action="submit" submissionId={props.ID}/>
|
||||||
<ReviewButton color="info" name="Revoke" action="revoke" submissionId={props.submissionId}/>
|
<ReviewButton color="info" name="Revoke" action="revoke" submissionId={props.ID}/>
|
||||||
<ReviewButton color="info" name="Accept" action="trigger-validate" submissionId={props.submissionId}/>
|
<ReviewButton color="info" name="Accept" action="trigger-validate" submissionId={props.ID}/>
|
||||||
<ReviewButton color="info" name="Validate" action="trigger-validate" submissionId={props.submissionId}/>
|
<ReviewButton color="info" name="Validate" action="trigger-validate" submissionId={props.ID}/>
|
||||||
<ReviewButton color="error" name="Reject" action="reject" submissionId={props.submissionId}/>
|
<ReviewButton color="error" name="Reject" action="reject" submissionId={props.ID}/>
|
||||||
<ReviewButton color="info" name="Upload" action="trigger-upload" submissionId={props.submissionId}/>
|
<ReviewButton color="info" name="Upload" action="trigger-upload" submissionId={props.ID}/>
|
||||||
<ReviewButton color="info" name="Completed" action="completed" submissionId={props.submissionId}/>
|
<ReviewButton color="info" name="Completed" action="completed" submissionId={props.ID}/>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { SubmissionStatus, SubmissionStatusToString } from "@/app/ts/Submission";
|
import { SubmissionInfo, SubmissionStatus, SubmissionStatusToString } from "@/app/ts/Submission";
|
||||||
import type { CreatorAndReviewStatus } from "./_comments";
|
import type { CreatorAndReviewStatus } from "./_comments";
|
||||||
import { MapImage } from "./_map";
|
import { MapImage } from "./_map";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
@ -10,13 +10,10 @@ import Comments from "./_comments";
|
|||||||
import Webpage from "@/app/_components/webpage";
|
import Webpage from "@/app/_components/webpage";
|
||||||
import Window from "./_window";
|
import Window from "./_window";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
|
||||||
import "./(styles)/page.scss";
|
import "./(styles)/page.scss";
|
||||||
|
|
||||||
interface ReviewId {
|
|
||||||
submissionId: string
|
|
||||||
}
|
|
||||||
|
|
||||||
function Ratings() {
|
function Ratings() {
|
||||||
return (
|
return (
|
||||||
<Window className="rating-window" title="Rating">
|
<Window className="rating-window" title="Rating">
|
||||||
@ -38,14 +35,15 @@ function Ratings() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function RatingArea(submission: ReviewId) {
|
function RatingArea(submission: SubmissionInfo) {
|
||||||
return (
|
return (
|
||||||
<aside className="review-area">
|
<aside className="review-area">
|
||||||
<section className="map-image-area">
|
<section className="map-image-area">
|
||||||
<MapImage/>
|
<MapImage/>
|
||||||
</section>
|
</section>
|
||||||
<Ratings/>
|
<Ratings/>
|
||||||
<ReviewButtons submissionId={submission.submissionId}/>
|
{ReviewButtons(submission)}
|
||||||
|
{/* <ReviewButtons submissionId={submission.ID}/> */}
|
||||||
</aside>
|
</aside>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -57,6 +55,7 @@ function TitleAndComments(stats: CreatorAndReviewStatus) {
|
|||||||
<main className="review-info">
|
<main className="review-info">
|
||||||
<div>
|
<div>
|
||||||
<h1>{stats.name}</h1>
|
<h1>{stats.name}</h1>
|
||||||
|
{/* TODO: Fix review status, I think its displaying the wrong information idk */}
|
||||||
<aside data-review-status={stats.review} className="review-status">
|
<aside data-review-status={stats.review} className="review-status">
|
||||||
<p>{Review}</p>
|
<p>{Review}</p>
|
||||||
</aside>
|
</aside>
|
||||||
@ -71,12 +70,29 @@ function TitleAndComments(stats: CreatorAndReviewStatus) {
|
|||||||
export default function SubmissionInfoPage() {
|
export default function SubmissionInfoPage() {
|
||||||
const dynamicId = useParams<{submissionId: string}>()
|
const dynamicId = useParams<{submissionId: string}>()
|
||||||
|
|
||||||
|
const [submission, setSubmission] = useState(null)
|
||||||
|
|
||||||
|
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() {
|
||||||
|
const res = await fetch(`/api/submissions/${dynamicId.submissionId}`)
|
||||||
|
const data = await res.json()
|
||||||
|
setSubmission(data)
|
||||||
|
}
|
||||||
|
getSubmission()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
if (!submission) return (
|
||||||
|
<Webpage>
|
||||||
|
{/* TODO: Add skeleton loading thingy ? Maybe ? (https://mui.com/material-ui/react-skeleton/) */}
|
||||||
|
</Webpage>
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Webpage>
|
<Webpage>
|
||||||
<main className="map-page-main">
|
<main className="map-page-main">
|
||||||
<section className="review-section">
|
<section className="review-section">
|
||||||
<RatingArea submissionId={dynamicId.submissionId}/>
|
{RatingArea(submission)}
|
||||||
<TitleAndComments name={dynamicId.submissionId} creator="Quaternions" review={SubmissionStatus.Accepted} comments={[]}/>
|
<TitleAndComments name={submission.DisplayName} creator={submission.Creator} review={submission.StatusID} comments={[]}/>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</Webpage>
|
</Webpage>
|
||||||
|
17
web/src/app/submissions/_card.tsx
Normal file
17
web/src/app/submissions/_card.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import React from "react";
|
||||||
|
import Image from "next/image";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
export default function SubmissionCard({ id, displayName, author, rating }) {
|
||||||
|
return (
|
||||||
|
<Link href={`/submissions/${id}`}>
|
||||||
|
<div className="submissionCard">
|
||||||
|
{/* 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} />
|
||||||
|
<h3>{displayName}</h3>
|
||||||
|
<p>By {author}</p>
|
||||||
|
<p>⭐ {rating}</p> {/* TODO: paste the star element from submission/1 page */}
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
40
web/src/app/submissions/_loading.tsx
Normal file
40
web/src/app/submissions/_loading.tsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { Grid, Skeleton } from '@mui/material';
|
||||||
|
|
||||||
|
const SkeletonGrid = () => {
|
||||||
|
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(() => {
|
||||||
|
calculateSkeletonCount();
|
||||||
|
window.addEventListener('resize', calculateSkeletonCount);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('resize', calculateSkeletonCount);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
spacing={2}
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="center"
|
||||||
|
style={{ maxWidth: 'calc(100vw - 100px)', margin: '0 auto' }}
|
||||||
|
>
|
||||||
|
{Array.from({ length: skeletonCount }).map((_, index) => (
|
||||||
|
<Grid item key={index}>
|
||||||
|
<Skeleton variant="rectangular" width={215} height={340} />
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SkeletonGrid;
|
20
web/src/app/submissions/_window.tsx
Normal file
20
web/src/app/submissions/_window.tsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
interface WindowStruct {
|
||||||
|
className: string,
|
||||||
|
title: string,
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Window(window: WindowStruct) {
|
||||||
|
return (
|
||||||
|
<section className={window.className}>
|
||||||
|
<header>
|
||||||
|
<p>{window.title}</p>
|
||||||
|
</header>
|
||||||
|
<main>{window.children}</main>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
type WindowStruct
|
||||||
|
}
|
75
web/src/app/submissions/page.tsx
Normal file
75
web/src/app/submissions/page.tsx
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import React, { useState, useEffect } from 'react'
|
||||||
|
import Webpage from "@/app/_components/webpage";
|
||||||
|
import { Grid2 as Grid } from '@mui/material';
|
||||||
|
import SubmissionCard from "./_card";
|
||||||
|
import SkeletonGrid from './_loading';
|
||||||
|
|
||||||
|
import "./(styles)/page.scss";
|
||||||
|
|
||||||
|
export default function SubmissionInfoPage() {
|
||||||
|
const [submissions, setSubmissions] = useState(null)
|
||||||
|
|
||||||
|
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() {
|
||||||
|
const res = await fetch('/api/submissions?Page=1&Limit=100')
|
||||||
|
const data = await res.json()
|
||||||
|
setSubmissions(data)
|
||||||
|
}
|
||||||
|
setTimeout(() => { // testing loading screen made by chatGerbertPT
|
||||||
|
fetchSubmissions()
|
||||||
|
}, 250);
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
if (!submissions) return (
|
||||||
|
<Webpage>
|
||||||
|
<main style={{ display: 'flex', justifyContent: 'center', padding: '1rem' }}>
|
||||||
|
<SkeletonGrid />
|
||||||
|
</main>
|
||||||
|
</Webpage>
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
// TODO: Add filter settings & searchbar & page selector
|
||||||
|
<Webpage>
|
||||||
|
<main style={{ display: 'flex', justifyContent: 'center', padding: '1rem' }}>
|
||||||
|
<Grid
|
||||||
|
container
|
||||||
|
spacing={2}
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="center"
|
||||||
|
style={{ maxWidth: 'calc(100vw - 100px)', margin: '0 auto' }}
|
||||||
|
>
|
||||||
|
{submissions.map((submission) => (
|
||||||
|
<Grid key={submission.ID}>
|
||||||
|
<SubmissionCard
|
||||||
|
id={submission.ID}
|
||||||
|
assetId={submission.AssetId}
|
||||||
|
displayName={submission.DisplayName}
|
||||||
|
author={submission.Creator}
|
||||||
|
rating={submission.StatusID}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</main>
|
||||||
|
</Webpage>
|
||||||
|
)
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "ID": 1,
|
||||||
|
// "DisplayName": "81bfc7a",
|
||||||
|
// "Creator": "79fbe8d",
|
||||||
|
// "GameID": 1073741824,
|
||||||
|
// "CreatedAt": 1734490019,
|
||||||
|
// "UpdatedAt": 1734565641,
|
||||||
|
// "Submitter": 1,
|
||||||
|
// "AssetID": 6438937102481093,
|
||||||
|
// "AssetVersion": 1225679040570074,
|
||||||
|
// "Completed": false,
|
||||||
|
// "SubmissionType": 0,
|
||||||
|
// "TargetAssetID": 1057095197389979,
|
||||||
|
// "StatusID": 4
|
||||||
|
// }
|
||||||
|
}
|
@ -25,7 +25,6 @@
|
|||||||
}
|
}
|
||||||
& fieldset {
|
& fieldset {
|
||||||
border-color: rgb(100,100,100);
|
border-color: rgb(100,100,100);
|
||||||
|
|
||||||
}
|
}
|
||||||
& span {
|
& span {
|
||||||
color: white;
|
color: white;
|
||||||
|
65
web/src/app/submit/_game.tsx
Normal file
65
web/src/app/submit/_game.tsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { FormControl, Select, InputLabel, MenuItem } from "@mui/material";
|
||||||
|
import { styled } from '@mui/material/styles';
|
||||||
|
import InputBase from '@mui/material/InputBase';
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
// TODO: Properly style everything instead of pasting 🤚
|
||||||
|
|
||||||
|
type GameSelectionProps = {
|
||||||
|
game: string;
|
||||||
|
setGame: React.Dispatch<React.SetStateAction<string>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const BootstrapInput = styled(InputBase)(({ theme }) => ({
|
||||||
|
'label + &': {
|
||||||
|
marginTop: theme.spacing(3),
|
||||||
|
},
|
||||||
|
'& .MuiInputBase-input': {
|
||||||
|
backgroundColor: '#0000',
|
||||||
|
color: '#FFF',
|
||||||
|
border: '1px solid rgba(175, 175, 175, 0.66)',
|
||||||
|
fontSize: 16,
|
||||||
|
padding: '10px 26px 10px 12px',
|
||||||
|
transition: theme.transitions.create(['border-color', 'box-shadow']),
|
||||||
|
// Use the system font instead of the default Roboto font.
|
||||||
|
fontFamily: [
|
||||||
|
'-apple-system',
|
||||||
|
'BlinkMacSystemFont',
|
||||||
|
'"Segoe UI"',
|
||||||
|
'Roboto',
|
||||||
|
'"Helvetica Neue"',
|
||||||
|
'Arial',
|
||||||
|
'sans-serif',
|
||||||
|
'"Apple Color Emoji"',
|
||||||
|
'"Segoe UI Emoji"',
|
||||||
|
'"Segoe UI Symbol"',
|
||||||
|
].join(','),
|
||||||
|
'&:focus': {
|
||||||
|
borderRadius: 4,
|
||||||
|
borderColor: '#80bdff',
|
||||||
|
boxShadow: '0 0 0 0.2rem rgba(0,123,255,.25)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
export default function GameSelection({ game, setGame }: GameSelectionProps) {
|
||||||
|
const handleChange = (event: SelectChangeEvent) => {
|
||||||
|
setGame(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl>
|
||||||
|
<InputLabel sx={{ color: "#646464" }}>Game</InputLabel>
|
||||||
|
<Select
|
||||||
|
value={game}
|
||||||
|
label="Game"
|
||||||
|
onChange={handleChange}
|
||||||
|
input={<BootstrapInput />}
|
||||||
|
>
|
||||||
|
<MenuItem value={1}>Bhop</MenuItem>
|
||||||
|
<MenuItem value={2}>Surf</MenuItem>
|
||||||
|
<MenuItem value={3}>Fly Trials</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
}
|
@ -1,12 +1,25 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { FormControl, FormLabel, RadioGroup, FormControlLabel, Button, TextField } from "@mui/material"
|
import { FormControl, FormLabel, RadioGroup, FormControlLabel, Button, TextField, Checkbox } from "@mui/material"
|
||||||
|
|
||||||
|
import GameSelection from "./_game";
|
||||||
import SendIcon from '@mui/icons-material/Send';
|
import SendIcon from '@mui/icons-material/Send';
|
||||||
import Webpage from "@/app/_components/webpage"
|
import Webpage from "@/app/_components/webpage"
|
||||||
import Radio from '@mui/material/Radio';
|
import Radio from '@mui/material/Radio';
|
||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import "./(styles)/page.scss"
|
import "./(styles)/page.scss"
|
||||||
|
|
||||||
|
interface SubmissionPayload {
|
||||||
|
DisplayName: string;
|
||||||
|
Creator: string;
|
||||||
|
GameID: number;
|
||||||
|
AssetID: number;
|
||||||
|
AssetVersion: number;
|
||||||
|
Submitter: number;
|
||||||
|
SubmissionType: number;
|
||||||
|
}
|
||||||
|
|
||||||
const enum Map {
|
const enum Map {
|
||||||
New,
|
New,
|
||||||
Fix,
|
Fix,
|
||||||
@ -23,6 +36,53 @@ function TargetAsset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function SubmissionInfoPage() {
|
export default function SubmissionInfoPage() {
|
||||||
|
const [game, setGame] = useState(1);
|
||||||
|
const [isFixingMap, setIsFixingMap] = useState(false);
|
||||||
|
|
||||||
|
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const form = event.currentTarget;
|
||||||
|
const formData = new FormData(form);
|
||||||
|
const data = {
|
||||||
|
displayName: formData.get("display-name"),
|
||||||
|
creator: formData.get("creator"),
|
||||||
|
assetId: formData.get("asset-id"),
|
||||||
|
game,
|
||||||
|
isFixingMap,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(data)
|
||||||
|
|
||||||
|
const payload: SubmissionPayload = {
|
||||||
|
DisplayName: data.displayName,
|
||||||
|
Creator: data.creator,
|
||||||
|
GameID: 1073741824, // TODO: Change this!!
|
||||||
|
AssetID: Number(data.assetId),
|
||||||
|
AssetVersion: 0,
|
||||||
|
SubmissionType: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(payload)
|
||||||
|
console.log(JSON.stringify(payload))
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Send the POST request
|
||||||
|
const response = await fetch("/api/submissions", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Allow any HTTP status
|
||||||
|
const responseText = await response.text();
|
||||||
|
|
||||||
|
console.log("Response Text:", responseText);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error submitting data:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Webpage>
|
<Webpage>
|
||||||
<main>
|
<main>
|
||||||
@ -30,20 +90,29 @@ export default function SubmissionInfoPage() {
|
|||||||
<h1>Submit Asset</h1>
|
<h1>Submit Asset</h1>
|
||||||
<span className="spacer form-spacer"></span>
|
<span className="spacer form-spacer"></span>
|
||||||
</header>
|
</header>
|
||||||
<form>
|
<form onSubmit={handleSubmit}>
|
||||||
<TextField className="form-field" id="display-name" label="Display Name" variant="outlined"/>
|
{/* TODO: Add form data for mapfixes, such as changes they did, and any times that need to be deleted & what styles */}
|
||||||
<TextField className="form-field" id="creator" label="Creator" variant="outlined"/>
|
<TextField className="form-field" id="display-name" name="display-name" label="Display Name" variant="outlined"/>
|
||||||
<TextField className="form-field" id="game-id" label="Game ID" variant="outlined"/>
|
<TextField className="form-field" id="creator" name="creator" label="Creator" variant="outlined"/>
|
||||||
<TextField className="form-field" id="asset-id" label="Asset ID" variant="outlined"/>
|
<TextField className="form-field" id="asset-id" name="asset-id" label="Asset ID" variant="outlined"/>
|
||||||
<TextField className="form-field" id="asset-version" label="Asset Version" variant="outlined"/>
|
{/* I think this is Quat's job to figure this one out (to be set when someone clicks review(?)) */} {/* <TextField className="form-field" id="asset-version" label="Asset Version" variant="outlined"/> */}
|
||||||
<TargetAsset/>
|
<GameSelection game={game} setGame={setGame} />
|
||||||
</form>
|
<FormControl>
|
||||||
|
<FormControlLabel control={<Checkbox sx={{
|
||||||
|
color: "#646464",
|
||||||
|
'&.Mui-checked': {
|
||||||
|
color: "#66BB6A",
|
||||||
|
},
|
||||||
|
}} onChange={(e) => setIsFixingMap(e.target.checked)} />} label="Fixing an Existing Map?" />
|
||||||
|
</FormControl>
|
||||||
|
{/* <TargetAsset/> */}
|
||||||
<span className="spacer form-spacer"></span>
|
<span className="spacer form-spacer"></span>
|
||||||
<Button variant="contained" startIcon={<SendIcon/>} sx={{
|
<Button type="submit" variant="contained" startIcon={<SendIcon/>} sx={{
|
||||||
width: "400px",
|
width: "400px",
|
||||||
height: "50px",
|
height: "50px",
|
||||||
marginInline: "auto"
|
marginInline: "auto"
|
||||||
}}>Submit</Button>
|
}}>Submit</Button>
|
||||||
|
</form>
|
||||||
</main>
|
</main>
|
||||||
</Webpage>
|
</Webpage>
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user