diff --git a/package-lock.json b/package-lock.json index 5121aba..3f00955 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@babel/plugin-syntax-import-attributes": "^7.23.3", "@headlessui/react": "^2.1.2", "@heroicons/react": "^1.0.6", + "@radix-ui/react-slot": "^1.1.0", "clsx": "^2.1.1", "comclub-website-2024": "file:", "date-fns": "^3.6.0", @@ -1100,6 +1101,37 @@ "node": ">=14" } }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@react-aria/focus": { "version": "3.17.1", "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.17.1.tgz", diff --git a/package.json b/package.json index 3fd5ff1..5a3bec4 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@babel/plugin-syntax-import-attributes": "^7.23.3", "@headlessui/react": "^2.1.2", "@heroicons/react": "^1.0.6", + "@radix-ui/react-slot": "^1.1.0", "clsx": "^2.1.1", "comclub-website-2024": "file:", "date-fns": "^3.6.0", diff --git a/src/components/Card.tsx b/src/components/Card.tsx new file mode 100644 index 0000000..354541e --- /dev/null +++ b/src/components/Card.tsx @@ -0,0 +1,79 @@ +import * as React from 'react'; + +import { cn } from '../../lib/utils'; + +const Card = React.forwardRef< +HTMLDivElement, +React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +Card.displayName = 'Card'; + +const CardHeader = React.forwardRef< +HTMLDivElement, +React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardHeader.displayName = 'CardHeader'; + +const CardTitle = React.forwardRef< +HTMLParagraphElement, +React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)); +CardTitle.displayName = 'CardTitle'; + +const CardDescription = React.forwardRef< +HTMLParagraphElement, +React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)); +CardDescription.displayName = 'CardDescription'; + +const CardContent = React.forwardRef< +HTMLDivElement, +React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)); +CardContent.displayName = 'CardContent'; + +const CardFooter = React.forwardRef< +HTMLDivElement, +React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardFooter.displayName = 'CardFooter'; + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }; diff --git a/src/components/Table.tsx b/src/components/Table.tsx new file mode 100644 index 0000000..1c9cc6b --- /dev/null +++ b/src/components/Table.tsx @@ -0,0 +1,117 @@ +import * as React from 'react'; + +import { cn } from '../../lib/utils'; + +const Table = React.forwardRef< +HTMLTableElement, +React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+ + +)); +Table.displayName = 'Table'; + +const TableHeader = React.forwardRef< +HTMLTableSectionElement, +React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableHeader.displayName = 'TableHeader'; + +const TableBody = React.forwardRef< +HTMLTableSectionElement, +React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableBody.displayName = 'TableBody'; + +const TableFooter = React.forwardRef< +HTMLTableSectionElement, +React.HTMLAttributes +>(({ className, ...props }, ref) => ( + tr]:last:border-b-0', + className, + )} + {...props} + /> +)); +TableFooter.displayName = 'TableFooter'; + +const TableRow = React.forwardRef< +HTMLTableRowElement, +React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableRow.displayName = 'TableRow'; + +const TableHead = React.forwardRef< +HTMLTableCellElement, +React.ThHTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +TableHead.displayName = 'TableHead'; + +const TableCell = React.forwardRef< +HTMLTableCellElement, +React.TdHTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableCell.displayName = 'TableCell'; + +const TableCaption = React.forwardRef< +HTMLTableCaptionElement, +React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +TableCaption.displayName = 'TableCaption'; + +export { + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption, +}; diff --git a/src/pages/elections/Candidates.tsx b/src/pages/elections/Candidates.tsx index faba4bb..8aead58 100644 --- a/src/pages/elections/Candidates.tsx +++ b/src/pages/elections/Candidates.tsx @@ -4,6 +4,7 @@ import { AnimatePresence, motion } from 'framer-motion'; import { useOutsideClick } from '../../../hooks/use-outside-click'; import WindowCard from '../../layout/WindowCard'; import { cards } from './constants'; +import Results from './Results'; export function Candidates() { const [active, setActive] = useState<(typeof cards)[number] | boolean | null>( @@ -86,6 +87,7 @@ export function Candidates() { return (
+

Candidates

See the candidates running for the NUS Students' Computing Club diff --git a/src/pages/elections/Results.tsx b/src/pages/elections/Results.tsx new file mode 100644 index 0000000..8fd05fa --- /dev/null +++ b/src/pages/elections/Results.tsx @@ -0,0 +1,121 @@ +import { + Card, + CardHeader, + CardTitle, + CardDescription, + CardContent, +} from '../../components/Card'; +import { + Table, + TableHeader, + TableRow, + TableHead, + TableBody, + TableCell, +} from '../../components/Table'; +import React from 'react'; +import { electionsResults } from './constants'; + +export default function Results() { + return ( +

+
+ + +
+
+ + 2024 Computing Club Election Results + + + Results of the recent election + +
+
+
+ +
+ + + + Total Votes + + + + +
354
+
+
+ + + + Total Candidates + + + + +
14
+
+
+
+
+
+ + + Results + + + + + + Rank + Candidate + For + Abstain + Against + Percentage + + + + {electionsResults.sort((a, b) => ('' + a.name).localeCompare(b.name)).map((result, index) => ( + + + {index + 1} + + {result.name} + {result.for} + {result.abstain} + {result.against} + = 50 ? 'text-green-500' : 'text-red-500'} font-semibold`}>{result.final}% + + ))} + +
+
+
+
+
+ ); +} + +function UsersIcon(props) { + return ( + + + + + + + ); +} diff --git a/src/pages/elections/constants.jsx b/src/pages/elections/constants.jsx index 4983d7a..b620624 100644 --- a/src/pages/elections/constants.jsx +++ b/src/pages/elections/constants.jsx @@ -625,3 +625,118 @@ export const cards = [ }, }, ]; + +export const electionsResults = [ + { + id: 1, + name: 'Chen Dong Jun', + abstain: 167, + for: 142, + against: 45, + final: 75.9, + }, + { + id: 2, + name: 'Choong Jing Xiang', + abstain: 162, + for: 154, + against: 38, + final: 80.2, + }, + { + id: 3, + name: 'Gowri Sumesh Menon', + abstain: 190, + for: 108, + against: 56, + final: 65.9, + }, + { + id: 4, + name: 'Jha Satwik', + abstain: 179, + for: 131, + against: 44, + final: 74.9, + }, + { + id: 5, + name: 'Lee Miao En Emelyn', + abstain: 159, + for: 151, + against: 44, + final: 77.4, + }, + { + id: 6, + name: 'Leow Sze Theng Jolyn', + abstain: 127, + for: 194, + against: 33, + final: 85.5, + }, + { + id: 7, + name: 'Liu Yuhang', + abstain: 69, + for: 113, + against: 172, + final: 39.7, + }, + { + id: 8, + name: 'Mu Junrong', + abstain: 185, + for: 89, + against: 80, + final: 52.7, + }, + { + id: 9, + name: 'Neo Ryan', + abstain: 179, + for: 122, + against: 53, + final: 69.7, + }, + { + id: 10, + name: 'Parama Roy Poja', + abstain: 184, + for: 103, + against: 67, + final: 60.6, + }, + { + id: 11, + name: 'Raeeda Ibnat Hossain', + abstain: 97, + for: 166, + against: 91, + final: 64.6, + }, + { + id: 12, + name: 'Ravichandran Gokul', + abstain: 187, + for: 116, + against: 51, + final: 69.5, + }, + { + id: 13, + name: 'Shananth Sivakumar', + abstain: 193, + for: 113, + against: 48, + final: 70.2, + }, + { + id: 14, + name: 'Sun Jiaen', + abstain: 164, + for: 121, + against: 69, + final: 63.7, + }, +];