Skip to content

Commit dfca2d9

Browse files
sosweethamSahil2004coodos
authored
Feat/evoting (#273)
* fix: remove cache folder * feat: login page * fix: frontend deps * fix: add poll and vote entities * feat: add service and controller pseudocode * fix: lock * fix: remove build artifacts * fix: better voting logic * fix: fixed the styling of evoting login page. * fix: fixed the styling of register page. * feat: added error showing in login on evoting. * feat: added the evoting disclaimer modal. --------- Co-authored-by: Sahil Garg <[email protected]> Co-authored-by: Merul Dhiman <[email protected]>
1 parent 04da1d3 commit dfca2d9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+3106
-457
lines changed

evoting.compose.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
services:
2+
db:
3+
image: postgres:16
4+
container_name: dev-evoting-db
5+
environment:
6+
POSTGRES_USER: evoting
7+
POSTGRES_PASSWORD: evoting
8+
POSTGRES_DB: evoting
9+
volumes:
10+
- ./db/data:/var/lib/postgresql/data
11+
ports:
12+
- "5432:5432"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cache

infrastructure/control-panel/project.inlang/cache/plugins/2sy648wh9sugi

Lines changed: 0 additions & 1 deletion
This file was deleted.

infrastructure/control-panel/project.inlang/cache/plugins/ygx0uiahq6uw

Lines changed: 0 additions & 16 deletions
This file was deleted.

platforms/eVoting/package.json

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,43 @@
11
{
2-
"name": "evoting",
3-
"version": "0.1.0",
4-
"private": true,
5-
"scripts": {
6-
"dev": "next dev --turbopack",
7-
"build": "next build",
8-
"start": "next start",
9-
"lint": "next lint"
10-
},
11-
"dependencies": {
12-
"@hookform/resolvers": "^3.10.0",
13-
"@radix-ui/react-label": "^2.1.3",
14-
"@radix-ui/react-radio-group": "^1.2.4",
15-
"@radix-ui/react-slot": "^1.2.0",
16-
"@tailwindcss/typography": "^0.5.16",
17-
"class-variance-authority": "^0.7.1",
18-
"clsx": "^2.1.1",
19-
"lucide-react": "^0.453.0",
20-
"next": "15.4.2",
21-
"react": "19.1.0",
22-
"react-dom": "19.1.0",
23-
"react-hook-form": "^7.55.0",
24-
"tailwind-merge": "^3.3.1",
25-
"tailwindcss-animate": "^1.0.7",
26-
"zod": "^3.24.2"
27-
},
28-
"devDependencies": {
29-
"@eslint/eslintrc": "^3",
30-
"@tailwindcss/postcss": "^4",
31-
"@types/node": "^20",
32-
"@types/react": "^19",
33-
"@types/react-dom": "^19",
34-
"eslint": "^9",
35-
"eslint-config-next": "15.4.2",
36-
"tailwindcss": "^4",
37-
"typescript": "^5"
38-
}
2+
"name": "evoting",
3+
"version": "0.1.0",
4+
"private": true,
5+
"scripts": {
6+
"dev": "next dev --turbopack",
7+
"build": "next build",
8+
"start": "next start",
9+
"lint": "next lint"
10+
},
11+
"dependencies": {
12+
"@hookform/resolvers": "^5.2.1",
13+
"@radix-ui/react-dialog": "^1.1.14",
14+
"@radix-ui/react-dropdown-menu": "^2.1.15",
15+
"@radix-ui/react-label": "^2.1.3",
16+
"@radix-ui/react-radio-group": "^1.2.4",
17+
"@radix-ui/react-slot": "^1.2.0",
18+
"@tailwindcss/typography": "^0.5.16",
19+
"better-auth": "^1.3.4",
20+
"class-variance-authority": "^0.7.1",
21+
"clsx": "^2.1.1",
22+
"lucide-react": "^0.453.0",
23+
"next": "15.4.2",
24+
"next-qrcode": "^2.5.1",
25+
"react": "19.1.0",
26+
"react-dom": "19.1.0",
27+
"react-hook-form": "^7.55.0",
28+
"tailwind-merge": "^3.3.1",
29+
"tailwindcss-animate": "^1.0.7",
30+
"zod": "^4.0.14"
31+
},
32+
"devDependencies": {
33+
"@eslint/eslintrc": "^3",
34+
"@tailwindcss/postcss": "^4",
35+
"@types/node": "^20",
36+
"@types/react": "^19",
37+
"@types/react-dom": "^19",
38+
"eslint": "^9",
39+
"eslint-config-next": "15.4.2",
40+
"tailwindcss": "^4",
41+
"typescript": "^5"
42+
}
3943
}

platforms/eVoting/public/Logo.png

5.63 KB
Loading

platforms/eVoting/public/W3DS.svg

Lines changed: 15 additions & 0 deletions
Loading
File renamed without changes.

platforms/eVoting/src/app/create/page.tsx renamed to platforms/eVoting/src/app/(app)/create/page.tsx

Lines changed: 125 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
11
"use client";
22

3-
import { useState, useEffect } from "react";
3+
import { useState } from "react";
44
import { useForm } from "react-hook-form";
55
import { zodResolver } from "@hookform/resolvers/zod";
66
import { z } from "zod";
7-
import { Plus, X, Eye, UserX } from "lucide-react";
7+
import {
8+
Plus,
9+
X,
10+
Eye,
11+
UserX,
12+
ChartLine,
13+
ListOrdered,
14+
CircleUser,
15+
} from "lucide-react";
816
import { Button } from "@/components/ui/button";
917
import { Input } from "@/components/ui/input";
1018
import { Label } from "@/components/ui/label";
1119
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
1220
import { useToast } from "@/hooks/use-toast";
13-
import { useAuth } from "@/hooks/useAuth";
14-
import { isUnauthorizedError } from "@/lib/authUtils";
1521
import Link from "next/link";
1622

1723
const createPollSchema = z.object({
1824
title: z.string().min(1, "Poll title is required"),
19-
mode: z.enum(["public", "private"]),
25+
mode: z.enum(["normal", "point", "rank"]),
26+
visibility: z.enum(["public", "private"]),
2027
options: z
2128
.array(z.string().min(1, "Option cannot be empty"))
2229
.min(2, "At least 2 options required"),
@@ -26,32 +33,16 @@ const createPollSchema = z.object({
2633
.refine((val) => {
2734
if (!val) return true; // Allow empty deadline
2835
const date = new Date(val);
29-
return !isNaN(date.getTime()) && date > new Date();
36+
return !Number.isNaN(date.getTime()) && date > new Date();
3037
}, "Deadline must be a valid future date"),
3138
});
3239

3340
type CreatePollForm = z.infer<typeof createPollSchema>;
3441

3542
export default function CreatePoll() {
3643
const { toast } = useToast();
37-
const { isAuthenticated, isLoading: authLoading } = useAuth();
3844
const [options, setOptions] = useState<string[]>(["", ""]);
3945

40-
// TODO: Redirect to login if not authenticated
41-
// useEffect(() => {
42-
// if (!authLoading && !isAuthenticated) {
43-
// toast({
44-
// title: "Unauthorized",
45-
// description: "You are logged out. Logging in again...",
46-
// variant: "destructive",
47-
// });
48-
// setTimeout(() => {
49-
// window.location.href = "/api/login";
50-
// }, 500);
51-
// return;
52-
// }
53-
// }, [isAuthenticated, authLoading, toast]);
54-
5546
const {
5647
register,
5748
handleSubmit,
@@ -62,13 +53,20 @@ export default function CreatePoll() {
6253
resolver: zodResolver(createPollSchema),
6354
defaultValues: {
6455
title: "",
65-
mode: "public",
56+
mode: "normal",
57+
visibility: "public",
6658
options: ["", ""],
6759
deadline: "",
6860
},
6961
});
7062

63+
handleSubmit((data) => {
64+
console.log("Form submitted:", data);
65+
console.log(data);
66+
});
67+
7168
const watchedMode = watch("mode");
69+
const watchedVisibility = watch("visibility");
7270

7371
const addOption = () => {
7472
const newOptions = [...options, ""];
@@ -132,7 +130,107 @@ export default function CreatePoll() {
132130
<RadioGroup
133131
value={watchedMode}
134132
onValueChange={(value) =>
135-
setValue("mode", value as "public" | "private")
133+
setValue(
134+
"mode",
135+
value as "normal" | "point" | "rank"
136+
)
137+
}
138+
className="mt-2"
139+
>
140+
<div className="flex items-center space-x-4">
141+
<Label className="flex items-center cursor-pointer">
142+
<RadioGroupItem
143+
value="normal"
144+
className="sr-only"
145+
/>
146+
<div
147+
className={`border-2 rounded-lg p-4 flex-1 transition-all ${
148+
watchedMode === "normal"
149+
? "border-(--crimson) bg-(--crimson-50)"
150+
: "border-gray-300 hover:border-(--crimson)"
151+
}`}
152+
>
153+
<div className="flex items-center">
154+
<CircleUser className="text-(--crimson) w-6 h-6 mr-3" />
155+
<div>
156+
<div className="font-semibold text-gray-900">
157+
1P 1V
158+
</div>
159+
<div className="text-sm text-gray-600">
160+
One person, one vote
161+
</div>
162+
</div>
163+
</div>
164+
</div>
165+
</Label>
166+
167+
<Label className="flex items-center cursor-pointer">
168+
<RadioGroupItem
169+
value="point"
170+
className="sr-only"
171+
/>
172+
<div
173+
className={`border-2 rounded-lg p-4 flex-1 transition-all ${
174+
watchedMode === "point"
175+
? "border-(--crimson) bg-(--crimson-50)"
176+
: "border-gray-300 hover:border-(--crimson)"
177+
}`}
178+
>
179+
<div className="flex items-center">
180+
<ChartLine className="text-(--crimson) w-6 h-6 mr-3" />
181+
<div>
182+
<div className="font-semibold text-gray-900">
183+
PBV
184+
</div>
185+
<div className="text-sm text-gray-600">
186+
Each voter gets 100 points
187+
</div>
188+
</div>
189+
</div>
190+
</div>
191+
</Label>
192+
193+
<Label className="flex items-center cursor-pointer">
194+
<RadioGroupItem
195+
value="rank"
196+
className="sr-only"
197+
/>
198+
<div
199+
className={`border-2 rounded-lg p-4 flex-1 transition-all ${
200+
watchedMode === "rank"
201+
? "border-(--crimson) bg-(--crimson-50)"
202+
: "border-gray-300 hover:border-(--crimson)"
203+
}`}
204+
>
205+
<div className="flex items-center">
206+
<ListOrdered className="text-(--crimson) w-6 h-6 mr-3" />
207+
<div>
208+
<div className="font-semibold text-gray-900">
209+
RBV
210+
</div>
211+
<div className="text-sm text-gray-600">
212+
Voters can rank order the
213+
choices
214+
</div>
215+
</div>
216+
</div>
217+
</div>
218+
</Label>
219+
</div>
220+
</RadioGroup>
221+
</div>
222+
223+
<div>
224+
<Label className="text-sm font-semibold text-gray-700">
225+
Vote Visibility
226+
</Label>
227+
<RadioGroup
228+
value={watchedVisibility}
229+
onValueChange={(value) =>
230+
setValue(
231+
"visibility",
232+
value as "public" | "private"
233+
)
136234
}
137235
className="mt-2"
138236
>
@@ -144,7 +242,7 @@ export default function CreatePoll() {
144242
/>
145243
<div
146244
className={`border-2 rounded-lg p-4 flex-1 transition-all ${
147-
watchedMode === "public"
245+
watchedVisibility === "public"
148246
? "border-(--crimson) bg-(--crimson-50)"
149247
: "border-gray-300 hover:border-(--crimson)"
150248
}`}
@@ -170,7 +268,7 @@ export default function CreatePoll() {
170268
/>
171269
<div
172270
className={`border-2 rounded-lg p-4 flex-1 transition-all ${
173-
watchedMode === "private"
271+
watchedVisibility === "private"
174272
? "border-(--crimson) bg-(--crimson-50)"
175273
: "border-gray-300 hover:border-(--crimson)"
176274
}`}
@@ -224,6 +322,7 @@ export default function CreatePoll() {
224322
<div className="mt-2 space-y-3">
225323
{options.map((option, index) => (
226324
<div
325+
// biome-ignore lint/suspicious/noArrayIndexKey: jatt dont care OOOOOOOOOO
227326
key={index}
228327
className="flex items-center space-x-2"
229328
>
@@ -278,21 +377,8 @@ export default function CreatePoll() {
278377
</Link>
279378
<Button
280379
type="submit"
281-
// disabled={createPollMutation.isPending}
282-
disabled={false} // TODO: replace with actual loading state
283380
className="flex-1 bg-(--crimson) hover:bg-(--crimson-50) hover:text-(--crimson) hover:border-(--crimson) border text-white"
284381
>
285-
{/* {createPollMutation.isPending ? (
286-
<>
287-
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2" />
288-
Creating...
289-
</>
290-
) : (
291-
<>
292-
<Plus className="w-4 h-4 mr-2" />
293-
Create Vote
294-
</>
295-
)} */}
296382
Create Vote
297383
</Button>
298384
</div>

0 commit comments

Comments
 (0)