diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx new file mode 100644 index 0000000..5d06e0e --- /dev/null +++ b/components/ui/badge.tsx @@ -0,0 +1,29 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; +import { type VariantProps, cva } from "class-variance-authority"; + +const badgeVariants = cva( + "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", + secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + }, +); + +export interface BadgeProps extends React.HTMLAttributes, VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return
; +} + +export { Badge, badgeVariants }; diff --git a/components/ui/label.tsx b/components/ui/label.tsx new file mode 100644 index 0000000..131ebf6 --- /dev/null +++ b/components/ui/label.tsx @@ -0,0 +1,19 @@ +"use client"; + +import * as React from "react"; + +import { cn } from "@/lib/utils"; +import * as LabelPrimitive from "@radix-ui/react-label"; +import { type VariantProps, cva } from "class-variance-authority"; + +const labelVariants = cva("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"); + +const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & VariantProps +>(({ className, ...props }, ref) => ( + +)); +Label.displayName = LabelPrimitive.Root.displayName; + +export { Label }; diff --git a/components/ui/table.tsx b/components/ui/table.tsx new file mode 100644 index 0000000..5461e9c --- /dev/null +++ b/components/ui/table.tsx @@ -0,0 +1,72 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const Table = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ + + ), +); +Table.displayName = "Table"; + +const TableHeader = React.forwardRef>( + ({ className, ...props }, ref) => , +); +TableHeader.displayName = "TableHeader"; + +const TableBody = React.forwardRef>( + ({ className, ...props }, ref) => ( + + ), +); +TableBody.displayName = "TableBody"; + +const TableFooter = React.forwardRef>( + ({ className, ...props }, ref) => ( + tr]:last:border-b-0", className)} {...props} /> + ), +); +TableFooter.displayName = "TableFooter"; + +const TableRow = React.forwardRef>( + ({ className, ...props }, ref) => ( + + ), +); +TableRow.displayName = "TableRow"; + +const TableHead = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ), +); +TableHead.displayName = "TableHead"; + +const TableCell = React.forwardRef>( + ({ className, ...props }, ref) => ( + + ), +); +TableCell.displayName = "TableCell"; + +const TableCaption = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ), +); +TableCaption.displayName = "TableCaption"; + +export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption }; diff --git a/package-lock.json b/package-lock.json index cae869e..951edbc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,9 +13,11 @@ "@emotion/styled": "^11.11.0", "@mui/material": "^5.16.4", "@radix-ui/react-dialog": "^1.1.1", + "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-toast": "^1.2.1", "@reduxjs/toolkit": "^1.9.6", + "@tanstack/react-query": "^5.59.0", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/node": "20.6.3", "@types/react": "18.2.22", @@ -42,6 +44,7 @@ "typescript": "5.2.2" }, "devDependencies": { + "@iconify/react": "^5.0.2", "@typescript-eslint/eslint-plugin": "^6.21.0", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-promise": "^6.4.0", @@ -548,6 +551,27 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==" }, + "node_modules/@iconify/react": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@iconify/react/-/react-5.0.2.tgz", + "integrity": "sha512-wtmstbYlEbo4NDxFxBJkhkf9gJBDqMGr7FaqLrAUMneRV3Z+fVHLJjOhWbkAF8xDQNFC/wcTYdrWo1lnRhmagQ==", + "dev": true, + "dependencies": { + "@iconify/types": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/cyberalien" + }, + "peerDependencies": { + "react": ">=16" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "dev": true + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -1166,6 +1190,28 @@ } } }, + "node_modules/@radix-ui/react-label": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.0.tgz", + "integrity": "sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-portal": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.1.tgz", @@ -1404,6 +1450,30 @@ "tslib": "^2.4.0" } }, + "node_modules/@tanstack/query-core": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.59.0.tgz", + "integrity": "sha512-WGD8uIhX6/deH/tkZqPNcRyAhDUqs729bWKoByYHSogcshXfFbppOdTER5+qY7mFvu8KEFJwT0nxr8RfPTVh0Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.59.0.tgz", + "integrity": "sha512-YDXp3OORbYR+8HNQx+lf4F73NoiCmCcSvZvgxE29OifmQFk0sBlO26NWLHpcNERo92tVk3w+JQ53/vkcRUY1hA==", + "dependencies": { + "@tanstack/query-core": "5.59.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, "node_modules/@trivago/prettier-plugin-sort-imports": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz", diff --git a/package.json b/package.json index e450ddb..bbf9a3b 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,11 @@ "@emotion/styled": "^11.11.0", "@mui/material": "^5.16.4", "@radix-ui/react-dialog": "^1.1.1", + "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-toast": "^1.2.1", "@reduxjs/toolkit": "^1.9.6", + "@tanstack/react-query": "^5.59.0", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/node": "20.6.3", "@types/react": "18.2.22", @@ -42,6 +44,7 @@ "typescript": "5.2.2" }, "devDependencies": { + "@iconify/react": "^5.0.2", "@typescript-eslint/eslint-plugin": "^6.21.0", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-promise": "^6.4.0", diff --git a/src/app/api/jerseyBidding.js b/src/app/api/jerseyBidding.js new file mode 100644 index 0000000..fa061fa --- /dev/null +++ b/src/app/api/jerseyBidding.js @@ -0,0 +1,28 @@ +import axios from "axios"; + +axios.defaults.withCredentials = true; + +// Does a call for User's bidding info +export const getUserBiddings = async () => { + try { + const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_URL}/jersey/info`); + + if (response.data.success) { + return response.data.data; + } + } catch (error) { + console.error("Error during getting user bids", error); + } +}; + +export const getUserEligibleBids = async () => { + try { + const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_URL}/jersey/eligible`); + + if (response.data.success) { + return response.data.data; + } + } catch (error) { + console.error("Error during getting user bids", error); + } +}; diff --git a/src/app/components/BiddingTable.tsx b/src/app/components/BiddingTable.tsx index 5f354f2..e7a2832 100644 --- a/src/app/components/BiddingTable.tsx +++ b/src/app/components/BiddingTable.tsx @@ -1,53 +1,123 @@ import React from "react"; +import { useState } from "react"; -import type { Bidding } from "@/src/app/dashboard/jersey/page"; -import type { ToastMessage } from "@/src/app/dashboard/jersey/page"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; +import { QueryObserverResult } from "@tanstack/react-query"; +import axios from "axios"; +import { Trash2 } from "lucide-react"; + +import { BiddingData, EligibleBids, UserBid } from "../dashboard/jersey/types"; interface BiddingList { - biddings: Bidding[]; - setBiddings: React.Dispatch>; - updateUser: () => void; - setToast: React.Dispatch>; - handleOpen: () => void; + userBids: UserBid; + refetchUserBids: () => Promise>; + biddings: BiddingData; + userEligibleBids: EligibleBids; + // setBiddings: React.Dispatch>; + // updateUser: () => void; + // setToast: React.Dispatch>; + // handleOpen: () => void; } -const axios = require("axios"); -const axiosWithCredentials = axios.create({ - withCredentials: true, -}); +axios.defaults.withCredentials = true; + +// User submit bid form +const BiddingTable: React.FC = ({ userBids, refetchUserBids, biddings, userEligibleBids }) => { + const [open, setOpen] = useState(false); + const [selectedNumber, setSelectedNumber] = useState(null); + const priority = userBids ? userBids.bids.length : 0; + + const curr_userBids = userBids.bids.map(bid => { + return { + number: bid.jersey.number, + priority: bid.priority, + }; + }); + + const canBid = userBids.canBid; -const BiddingTable: React.FC = ({ biddings, setBiddings, updateUser, setToast, handleOpen }) => { - const deleteBid = (ind: number) => { - const filteredList = biddings.filter(bidding => bidding.number != biddings[ind].number); - setBiddings(filteredList); + const handleOpenModal = (number: number) => { + setOpen(true); + setSelectedNumber(number); }; - // Currently unable to make the api call - const handleSubmit = async (e: React.MouseEvent) => { - e.preventDefault(); + const handlePlaceBid = async (number: number) => { + try { + const newBids = { + bids: [ + ...curr_userBids, + { + number, + priority: curr_userBids.length + 1, + }, + ], + }; + const resp = await axios.post(`${process.env.NEXT_PUBLIC_BACKEND_URL}/jersey/bid`, newBids); + + if (resp.status === 200) { + refetchUserBids(); + } + } catch (err) { + console.log(err); + } + }; + + const handleDeleteBid = async (number: number) => { try { - const response = await axiosWithCredentials.post(`${process.env.NEXT_PUBLIC_BACKEND_URL}/bid/create`, { - bids: biddings, + const newBids = curr_userBids.filter(bid => bid.number !== number); + const resp = await axios.post(`${process.env.NEXT_PUBLIC_BACKEND_URL}/jersey/bid`, { + bids: newBids, }); - if (response.data.success) { - setToast({ message: "Bids submitted", severity: "success" }); - handleOpen(); - updateUser(); - } else { - console.error("Bids failed"); - setToast({ message: "Bids failed to be submitted", severity: "error" }); - handleOpen(); + if (resp.status == 200) { + refetchUserBids(); } - } catch (error) { - console.error("Error during form submission", error); + } catch (err) { + console.log(err); } }; + // const getEligibleNumbers = () => { + // return userEligibleBids.bids.map(bid => bid.jersey.number); + // }; + + // const eligibleNumbers = getEligibleNumbers(); + + // const deleteBid = (ind: number) => { + // const filteredList = biddings.filter(bidding => bidding.number != biddings[ind].number); + // setBiddings(filteredList); + // }; + + // Currently unable to make the api call + // const handleSubmit = async (e: React.MouseEvent) => { + // e.preventDefault(); + // try { + // const response = await axiosWithCredentials.post(`${process.env.NEXT_PUBLIC_BACKEND_URL}/bid/create`, { + // biddings: biddings, + // }); + + // if (response.data.success) { + // setToast({ message: "biddings submitted", severity: "success" }); + // handleOpen(); + // updateUser(); + // } else { + // console.error("biddings failed"); + // setToast({ message: "biddings failed to be submitted", severity: "error" }); + // handleOpen(); + // } + // } catch (error) { + // console.error("Error during form submission", error); + // } + // }; + return ( -
+ /*
-

Submit new bids:

+

Submit new biddings:

= ({ biddings, setBiddings, updateUser

Ensure you click submit to confirm changes

- {biddings.length == 0 ? ( + {/* {biddings.length == 0 ? ( <> ) : ( - )} + )} }
@@ -93,14 +163,14 @@ const BiddingTable: React.FC = ({ biddings, setBiddings, updateUser - {biddings.map((bidding, index) => ( + {Object.entries(biddings).map(([jerseyNumber, bidding], index) => ( - - + + {/* }
{index + 1}{bidding.number}{jerseyNumber}{bidding.number} @@ -109,6 +179,153 @@ const BiddingTable: React.FC = ({ biddings, setBiddings, updateUser ))}
+ +
*/ +
+

Bidding Table

+ {userBids && ( + + + Your Bids + View and manage your current bids + + +
+
+
+

Status: {canBid ? "Can Bid" : "Cannot Bid"}

+
+
+

Points:

+

{userBids.info.points.toLocaleString()}

+
+
+

Teams :

+
+ {userBids.info.teams.map(team => ( + + {team.team.name} + + ))} +
+
+

Bids :

+
+ + + + Bidding Number + Priority + Actions + + + + {userBids.bids.map((bid, index) => ( + + {bid.jersey.number} + {bid.priority + 1} + +
+ +
+
+
+ ))} +
+
+
+
+
+
+ )} + +

Eligible Bidding Numbers :

+ +
+ {Array.from({ length: 100 }, (_, i) => i + 1).map(number => { + const isEligible = userEligibleBids !== undefined ? userEligibleBids.jerseys.includes(number) : false; // Check if the number is eligible + return ( + + ); + })} +
+ + + + + Biddings for Number {selectedNumber} + +

Your Points : {userBids.info.points}

+ {selectedNumber && biddings && biddings[selectedNumber] && ( +
+
Quota M: {biddings[selectedNumber].quota.male}
+
Quota F: {biddings[selectedNumber].quota.female}
+
+ )} +
+ + + + Room Number + User + + + + {selectedNumber && + biddings[selectedNumber] && + biddings[selectedNumber].male.map((bid, index) => ( + + {bid.user} (M) + ${bid.amount.toFixed(2)} + + ))} + {selectedNumber && + biddings[selectedNumber] && + biddings[selectedNumber].female.map((bid, index) => { + return ( + + {bid.user.room} (F) + {bid.points} + + ); + })} + + {/* {(!selectedNumber || !biddings[selectedNumber] || bids[selectedNumber].length === 0) && ( + + + No biddings yet + + + )} */} + +
+
+ + + +
+
); }; diff --git a/src/app/components/LoginForm.tsx b/src/app/components/LoginForm.tsx index 79a2916..a1eb033 100644 --- a/src/app/components/LoginForm.tsx +++ b/src/app/components/LoginForm.tsx @@ -19,7 +19,7 @@ export default function LoginForm() { useEffect(() => { if (user !== null) { - router.push(`/dashboard/profile`); + router.push(`/dashboard/jersey`); } }); @@ -48,7 +48,7 @@ export default function LoginForm() { }; dispatch(setUser(newUser)); - router.replace("/dashboard/profile"); + router.replace("/dashboard/jersey"); } } catch (error) { const axiosError = error as AxiosError; diff --git a/src/app/components/Modal/modal.tsx b/src/app/components/Modal/modal.tsx index ff0c2ad..637fdf6 100644 --- a/src/app/components/Modal/modal.tsx +++ b/src/app/components/Modal/modal.tsx @@ -1,187 +1,187 @@ -import React, { useEffect, useState } from "react"; - -import type { Bidding, ToastMessage } from "@/src/app/dashboard/jersey/page"; - -interface ModalProps { - closeModal: () => void; - index: number; - points: number; - biddings: Bidding[]; - setBiddings: React.Dispatch>; - setToast: React.Dispatch>; - handleOpen: () => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - currentList: any[]; -} - -interface User { - username: string; - points: number; -} - -const axios = require("axios"); -axios.defaults.withCredentials = true; - -const Modal: React.FC = ({ - closeModal, - index, - points, - biddings, - setBiddings, - setToast, - handleOpen, - // currentList, -}) => { - const [bidders, setBidders] = useState(null); - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - // const compareLists = (list: any[]): boolean => { - // for (let i = 0; i < currentList.length; i++) { - // for (let j = 0; j < list.length; j++) { - // if (currentList[i].name == list[j].name) { - // return true; - // } - // } - // } - // return false; - // }; - - // // eslint-disable-next-line @typescript-eslint/no-explicit-any - // const getNames = (list: any[]): string => { - // const names: string[] = []; - // for (let j = 0; j < list.length; j++) { - // names.push(list[j].name); - // } - - // return names.join(", "); - // }; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const fetchList: any = async () => { - try { - const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_URL}/jersey/info`); - - if (response.data.success) { - await setBidders(response.data.data[index]); - } - } catch (error) { - console.error("Error during update", error); - } - }; - - useEffect(() => { - fetchList(index); - }); - - const createBid = (ind: number) => { - const duplicateArr = biddings.filter(bidding => bidding.number == ind); - - if (duplicateArr.length !== 0) { - // Include a popup to tell user to not bid for duplicates - setToast({ message: "Cannot bid for duplicate numbers", severity: "error" }); - handleOpen(); - return; - } - - if (biddings.length > 4) { - //number is 4 because when open modal for 5th number, will record 4 numbers in bidding - // Include a popup to tell user not to bid for more than 5 numbers - setToast({ message: "Cannot bid for more than 5 numbers", severity: "error" }); - handleOpen(); - return; - } - - const newBidding: Bidding = { - number: ind, - }; - - setBiddings([...biddings, newBidding]); - }; - - return ( -
-
-
-
-

Bidding List

- -
- {bidders != null && ( -
-
-
Male Quota: {bidders.quota.Male}
-
Female Quota: {bidders.quota.Female}
-
- {bidders.Male.length > 0 || bidders.Female.length > 0 ? ( - - - - - - - - - - {Object.keys(bidders) - .filter(category => category == "Male" || category == "Female") - .map( - (category, index: number) => - bidders[category].length > 0 && ( - <> - - - - - - {bidders[category].map((item: User, subIndex: number) => ( - - - - - {/* */} - - ))} - - ), - )} - -
CategoryNamePointsSports
{category}
{item.username}{item.points}{getNames(item.teams)}
- ) : ( -

No Bids Found!!!

- )} -
- )} -
-

Current Points : {points}

- -
-
-
- ); -}; - -export default Modal; +// import React, { useEffect, useState } from "react"; + +// import type { Bidding, ToastMessage } from "@/src/app/dashboard/jersey/page"; + +// interface ModalProps { +// closeModal: () => void; +// index: number; +// points: number; +// biddings: Bidding[]; +// setBiddings: React.Dispatch>; +// setToast: React.Dispatch>; +// handleOpen: () => void; +// // eslint-disable-next-line @typescript-eslint/no-explicit-any +// currentList: any[]; +// } + +// interface User { +// username: string; +// points: number; +// } + +// const axios = require("axios"); +// axios.defaults.withCredentials = true; + +// const Modal: React.FC = ({ +// closeModal, +// index, +// points, +// biddings, +// setBiddings, +// setToast, +// handleOpen, +// // currentList, +// }) => { +// const [bidders, setBidders] = useState(null); + +// // eslint-disable-next-line @typescript-eslint/no-explicit-any +// // const compareLists = (list: any[]): boolean => { +// // for (let i = 0; i < currentList.length; i++) { +// // for (let j = 0; j < list.length; j++) { +// // if (currentList[i].name == list[j].name) { +// // return true; +// // } +// // } +// // } +// // return false; +// // }; + +// // // eslint-disable-next-line @typescript-eslint/no-explicit-any +// // const getNames = (list: any[]): string => { +// // const names: string[] = []; +// // for (let j = 0; j < list.length; j++) { +// // names.push(list[j].name); +// // } + +// // return names.join(", "); +// // }; + +// // eslint-disable-next-line @typescript-eslint/no-explicit-any +// const fetchList: any = async () => { +// try { +// const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_URL}/jersey/info`); + +// if (response.data.success) { +// await setBidders(response.data.data[index]); +// } +// } catch (error) { +// console.error("Error during update", error); +// } +// }; + +// useEffect(() => { +// fetchList(index); +// }); + +// const createBid = (ind: number) => { +// const duplicateArr = biddings.filter(bidding => bidding.number == ind); + +// if (duplicateArr.length !== 0) { +// // Include a popup to tell user to not bid for duplicates +// setToast({ message: "Cannot bid for duplicate numbers", severity: "error" }); +// handleOpen(); +// return; +// } + +// if (biddings.length > 4) { +// //number is 4 because when open modal for 5th number, will record 4 numbers in bidding +// // Include a popup to tell user not to bid for more than 5 numbers +// setToast({ message: "Cannot bid for more than 5 numbers", severity: "error" }); +// handleOpen(); +// return; +// } + +// const newBidding: Bidding = { +// number: ind, +// }; + +// setBiddings([...biddings, newBidding]); +// }; + +// return ( +//
+//
+//
+//
+//

Bidding List

+// +//
+// {bidders != null && ( +//
+//
+//
Male Quota: {bidders.quota.Male}
+//
Female Quota: {bidders.quota.Female}
+//
+// {bidders.Male.length > 0 || bidders.Female.length > 0 ? ( +// +// +// +// +// +// +// +// + +// {Object.keys(bidders) +// .filter(category => category == "Male" || category == "Female") +// .map( +// (category, index: number) => +// bidders[category].length > 0 && ( +// <> +// +// +// +// +// +// {bidders[category].map((item: User, subIndex: number) => ( +// +// +// +// +// {/* */} +// +// ))} +// +// ), +// )} +// +//
CategoryNamePointsSports
{category}
{item.username}{item.points}{getNames(item.teams)}
+// ) : ( +//

No Bids Found!!!

+// )} +//
+// )} +//
+//

Current Points : {points}

+// +//
+//
+//
+// ); +// }; + +// export default Modal; diff --git a/src/app/components/Modal/roomModal.tsx b/src/app/components/Modal/roomModal.tsx index 68199f0..4730cf2 100644 --- a/src/app/components/Modal/roomModal.tsx +++ b/src/app/components/Modal/roomModal.tsx @@ -1,189 +1,189 @@ -import React, { useEffect, useState } from "react"; - -import type { Bidding, ToastMessage } from "@/src/app/dashboard/jersey/page"; - -interface ModalProps { - closeModal: () => void; - index: number; - points: number; - biddings: Bidding[]; - setBiddings: React.Dispatch>; - setToast: React.Dispatch>; - handleOpen: () => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - currentList: any[]; -} - -interface User { - username: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - teams: any[]; - points: number; -} - -const axios = require("axios"); -axios.defaults.withCredentials = true; - -const Modal: React.FC = ({ - closeModal, - index, - points, - biddings, - setBiddings, - setToast, - handleOpen, - currentList, -}) => { - const [bidders, setBidders] = useState(null); - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const compareLists = (list: any[]): boolean => { - for (let i = 0; i < currentList.length; i++) { - for (let j = 0; j < list.length; j++) { - if (currentList[i].name == list[j].name) { - return true; - } - } - } - return false; - }; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const getNames = (list: any[]): string => { - const names: string[] = []; - for (let j = 0; j < list.length; j++) { - names.push(list[j].name); - } - - return names.join(", "); - }; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const fetchList: any = async () => { - try { - const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_URL}/jersey/info`); - - if (response.data.success) { - await setBidders(response.data.data[index]); - } - } catch (error) { - console.error("Error during update", error); - } - }; - - useEffect(() => { - fetchList(index); - }); - - const createBid = (ind: number) => { - const duplicateArr = biddings.filter(bidding => bidding.number == ind); - - if (duplicateArr.length !== 0) { - // Include a popup to tell user to not bid for duplicates - setToast({ message: "Cannot bid for duplicate numbers", severity: "error" }); - handleOpen(); - return; - } - - if (biddings.length > 4) { - //number is 4 because when open modal for 5th number, will record 4 numbers in bidding - // Include a popup to tell user not to bid for more than 5 numbers - setToast({ message: "Cannot bid for more than 5 numbers", severity: "error" }); - handleOpen(); - return; - } - - const newBidding: Bidding = { - number: ind, - }; - - setBiddings([...biddings, newBidding]); - }; - - return ( -
-
-
-
-

Bidding List

- -
- {bidders != null && ( -
-
-
Male Quota: {bidders.quota.Male}
-
Female Quota: {bidders.quota.Female}
-
- {bidders.Male.length > 0 || bidders.Female.length > 0 ? ( - - - - - - - - - - {Object.keys(bidders) - .filter(category => category == "Male" || category == "Female") - .map( - (category, index: number) => - bidders[category].length > 0 && ( - <> - - - - - - {bidders[category].map((item: User, subIndex: number) => ( - - - - - - - ))} - - ), - )} - -
CategoryNamePointsSports
{category}
{item.username}{item.points}{getNames(item.teams)}
- ) : ( -

No Bids Found!!!

- )} -
- )} -
-

Current Points : {points}

- -
-
-
- ); -}; - -export default Modal; +// import React, { useEffect, useState } from "react"; + +// import type { Bidding, ToastMessage } from "@/src/app/dashboard/jersey/page"; + +// interface ModalProps { +// closeModal: () => void; +// index: number; +// points: number; +// biddings: Bidding[]; +// setBiddings: React.Dispatch>; +// setToast: React.Dispatch>; +// handleOpen: () => void; +// // eslint-disable-next-line @typescript-eslint/no-explicit-any +// currentList: any[]; +// } + +// interface User { +// username: string; +// // eslint-disable-next-line @typescript-eslint/no-explicit-any +// teams: any[]; +// points: number; +// } + +// const axios = require("axios"); +// axios.defaults.withCredentials = true; + +// const Modal: React.FC = ({ +// closeModal, +// index, +// points, +// biddings, +// setBiddings, +// setToast, +// handleOpen, +// currentList, +// }) => { +// const [bidders, setBidders] = useState(null); + +// // eslint-disable-next-line @typescript-eslint/no-explicit-any +// const compareLists = (list: any[]): boolean => { +// for (let i = 0; i < currentList.length; i++) { +// for (let j = 0; j < list.length; j++) { +// if (currentList[i].name == list[j].name) { +// return true; +// } +// } +// } +// return false; +// }; + +// // eslint-disable-next-line @typescript-eslint/no-explicit-any +// const getNames = (list: any[]): string => { +// const names: string[] = []; +// for (let j = 0; j < list.length; j++) { +// names.push(list[j].name); +// } + +// return names.join(", "); +// }; + +// // eslint-disable-next-line @typescript-eslint/no-explicit-any +// const fetchList: any = async () => { +// try { +// const response = await axios.get(`${process.env.NEXT_PUBLIC_BACKEND_URL}/jersey/info`); + +// if (response.data.success) { +// await setBidders(response.data.data[index]); +// } +// } catch (error) { +// console.error("Error during update", error); +// } +// }; + +// useEffect(() => { +// fetchList(index); +// }); + +// const createBid = (ind: number) => { +// const duplicateArr = biddings.filter(bidding => bidding.number == ind); + +// if (duplicateArr.length !== 0) { +// // Include a popup to tell user to not bid for duplicates +// setToast({ message: "Cannot bid for duplicate numbers", severity: "error" }); +// handleOpen(); +// return; +// } + +// if (biddings.length > 4) { +// //number is 4 because when open modal for 5th number, will record 4 numbers in bidding +// // Include a popup to tell user not to bid for more than 5 numbers +// setToast({ message: "Cannot bid for more than 5 numbers", severity: "error" }); +// handleOpen(); +// return; +// } + +// const newBidding: Bidding = { +// number: ind, +// }; + +// setBiddings([...biddings, newBidding]); +// }; + +// return ( +//
+//
+//
+//
+//

Bidding List

+// +//
+// {bidders != null && ( +//
+//
+//
Male Quota: {bidders.quota.Male}
+//
Female Quota: {bidders.quota.Female}
+//
+// {bidders.Male.length > 0 || bidders.Female.length > 0 ? ( +// +// +// +// +// +// +// +// + +// {Object.keys(bidders) +// .filter(category => category == "Male" || category == "Female") +// .map( +// (category, index: number) => +// bidders[category].length > 0 && ( +// <> +// +// +// +// +// +// {bidders[category].map((item: User, subIndex: number) => ( +// +// +// +// +// +// +// ))} +// +// ), +// )} +// +//
CategoryNamePointsSports
{category}
{item.username}{item.points}{getNames(item.teams)}
+// ) : ( +//

No Bids Found!!!

+// )} +//
+// )} +//
+//

Current Points : {points}

+// +//
+//
+//
+// ); +// }; + +// export default Modal; diff --git a/src/app/components/NavBar.tsx b/src/app/components/NavBar.tsx index a81a13e..8e1bdca 100644 --- a/src/app/components/NavBar.tsx +++ b/src/app/components/NavBar.tsx @@ -2,6 +2,7 @@ import React from "react"; +import { Icon } from "@iconify/react"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { useDispatch } from "react-redux"; @@ -34,7 +35,7 @@ export default function NavBar() {