fix(api): fix api endpoint logic #1

This commit is contained in:
shafin-r
2025-08-10 19:25:25 +06:00
parent 0bca09f8ef
commit 713696760e
8 changed files with 138 additions and 84 deletions

2
.gitignore vendored
View File

@ -39,3 +39,5 @@ yarn-error.log*
# typescript # typescript
*.tsbuildinfo *.tsbuildinfo
next-env.d.ts next-env.d.ts
.vercel

View File

@ -22,13 +22,17 @@ export default function RegisterPage() {
const { setToken } = useAuth(); const { setToken } = useAuth();
const router = useRouter(); const router = useRouter();
const [form, setForm] = useState<RegisterForm>({ const [form, setForm] = useState<RegisterForm>({
name: "", full_name: "",
institution: "", username: "",
sscRoll: "",
hscRoll: "",
email: "", email: "",
phone: "",
password: "", password: "",
phone_number: "",
ssc_roll: 0,
ssc_board: "",
hsc_roll: 0,
hsc_board: "",
college: "",
preparation_unit: "",
}); });
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
@ -44,8 +48,8 @@ export default function RegisterPage() {
}; };
const validateForm = () => { const validateForm = () => {
const { sscRoll, hscRoll, password } = form; const { ssc_roll, hsc_roll, password } = form;
if (sscRoll === hscRoll) { if (ssc_roll === hsc_roll) {
return "SSC Roll and HSC Roll must be unique."; return "SSC Roll and HSC Roll must be unique.";
} }
const passwordRegex = const passwordRegex =
@ -93,11 +97,11 @@ export default function RegisterPage() {
return ( return (
<BackgroundWrapper> <BackgroundWrapper>
<div className="min-h-screen flex flex-col items-center justify-center px-4 py-10"> <div className="min-h-screen flex flex-col items-center justify-center px-4 py-10">
<div className="w-full max-w-md space-y-6"> <div className="w-full space-y-6">
<div className="w-full aspect-[368/89] mx-auto"> <div className="w-full aspect-[368/89] mx-auto">
<Image <Image
src="/images/logo/logo.png" src="/images/logo/logo.png"
alt="Logo" alt="logo"
width={368} width={368}
height={89} height={89}
className="w-full h-auto" className="w-full h-auto"
@ -106,48 +110,34 @@ export default function RegisterPage() {
<div className="space-y-10"> <div className="space-y-10">
<div className="space-y-6"> <div className="space-y-6">
<h1 className="text-2xl font-semibold">Personal Info</h1>
<FormField <FormField
title="Full name" title="Full name"
value={form.name} value={form.full_name}
handleChangeText={(value) => setForm({ ...form, name: value })}
/>
<FormField
title="Institution"
value={form.institution}
handleChangeText={(value) => handleChangeText={(value) =>
setForm({ ...form, institution: value }) setForm({ ...form, full_name: value })
} }
/> />
<FormField <FormField
title="SSC Roll No." title="User name"
value={form.sscRoll} value={form.username}
handleChangeText={(value) => handleChangeText={(value) =>
setForm({ ...form, sscRoll: value }) setForm({ ...form, username: value })
} }
/> />
<FormField <FormField
title="HSC Roll No." title="Phone Number"
value={form.hscRoll} value={form.phone_number}
handleChangeText={(value) => handleChangeText={(value) =>
setForm({ ...form, hscRoll: value }) setForm({ ...form, phone_number: value })
} }
/> />
<FormField <FormField
title="Email Address" title="Email Address"
value={form.email} value={form.email}
handleChangeText={(value) => setForm({ ...form, email: value })} handleChangeText={(value) => setForm({ ...form, email: value })}
/> />
<FormField
title="Phone Number"
value={form.phone}
handleChangeText={(value) => setForm({ ...form, phone: value })}
/>
<FormField <FormField
title="Password" title="Password"
value={form.password} value={form.password}
@ -156,6 +146,58 @@ export default function RegisterPage() {
} }
placeholder={undefined} placeholder={undefined}
/> />
<h1 className="text-2xl font-semibold">Educational Background</h1>
<FormField
title="College"
value={form.college}
handleChangeText={(value) =>
setForm({ ...form, college: value })
}
/>
<FormField
title="Preparation Unit"
value={form.preparation_unit}
handleChangeText={(value) =>
setForm({ ...form, preparation_unit: value })
}
/>
<div className="w-full flex gap-4">
<FormField
title="SSC Board"
value={form.ssc_board}
handleChangeText={(value) =>
setForm({ ...form, ssc_board: value })
}
/>
<FormField
title="SSC Roll No."
value={form.ssc_roll}
handleChangeText={(value: string) =>
setForm({ ...form, ssc_roll: Number(value) })
}
className="max-w-26"
/>
</div>
<div className="w-full flex gap-4">
<FormField
title="HSC Board"
value={form.hsc_board}
handleChangeText={(value) =>
setForm({ ...form, hsc_board: value })
}
/>
<FormField
title="HSC Roll No."
value={form.hsc_roll}
handleChangeText={(value: string) =>
setForm({ ...form, hsc_roll: Number(value) })
}
className="max-w-26"
/>
</div>
</div> </div>
{error && <DestructibleAlert text={error} />} {error && <DestructibleAlert text={error} />}

View File

@ -2,7 +2,7 @@
import { useSearchParams } from "next/navigation"; import { useSearchParams } from "next/navigation";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { Suspense, useEffect, useState } from "react"; import { useEffect, useState } from "react";
import Header from "@/components/Header"; import Header from "@/components/Header";
import DestructibleAlert from "@/components/DestructibleAlert"; import DestructibleAlert from "@/components/DestructibleAlert";
import BackgroundWrapper from "@/components/BackgroundWrapper"; import BackgroundWrapper from "@/components/BackgroundWrapper";
@ -14,8 +14,7 @@ interface Mock {
title: string; title: string;
rating: number; rating: number;
} }
export default function PaperScreen() {
function PaperPageContent() {
const router = useRouter(); const router = useRouter();
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const name = searchParams.get("name") || ""; const name = searchParams.get("name") || "";
@ -23,6 +22,7 @@ function PaperPageContent() {
const [questions, setQuestions] = useState<Mock[] | null>(null); const [questions, setQuestions] = useState<Mock[] | null>(null);
const [errorMsg, setErrorMsg] = useState<string | null>(null); const [errorMsg, setErrorMsg] = useState<string | null>(null);
const [refreshing, setRefreshing] = useState<boolean>(false); const [refreshing, setRefreshing] = useState<boolean>(false);
const [componentKey, setComponentKey] = useState<number>(0);
async function fetchMocks() { async function fetchMocks() {
try { try {
@ -44,13 +44,17 @@ function PaperPageContent() {
const onRefresh = async () => { const onRefresh = async () => {
setRefreshing(true); setRefreshing(true);
await fetchMocks(); await fetchMocks();
setComponentKey((prevKey) => prevKey + 1);
setTimeout(() => {
setRefreshing(false);
}, 1000);
}; };
if (errorMsg) { if (errorMsg) {
return ( return (
<BackgroundWrapper> <BackgroundWrapper>
<div className="min-h-screen">
<Header displayTabTitle={name} /> <Header displayTabTitle={name} />
<div className="overflow-y-auto"> <div className="overflow-y-auto">
<div className="mt-5 px-5"> <div className="mt-5 px-5">
@ -66,8 +70,6 @@ function PaperPageContent() {
</button> </button>
</div> </div>
</div> </div>
{/* <CustomBackHandler fallbackRoute="unit" /> */}
</div>
</BackgroundWrapper> </BackgroundWrapper>
); );
} }
@ -118,20 +120,3 @@ function PaperPageContent() {
</BackgroundWrapper> </BackgroundWrapper>
); );
} }
export default function PaperScreen() {
<Suspense
fallback={
<BackgroundWrapper>
<div className="min-h-screen">
<div className="mx-10 mt-10 flex flex-col justify-center items-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-900 mb-4"></div>
<p className="text-lg font-medium text-gray-900">Loading...</p>
</div>
</div>
</BackgroundWrapper>
}
>
<PaperPageContent />
</Suspense>;
}

BIN
bun.lockb

Binary file not shown.

9
capacitor.config.ts Normal file
View File

@ -0,0 +1,9 @@
import type { CapacitorConfig } from "@capacitor/cli";
const config: CapacitorConfig = {
appId: "com.examjam.solanine",
appName: "ExamJam",
webDir: "public",
};
export default config;

View File

@ -1,23 +1,32 @@
import React, { useState, InputHTMLAttributes } from "react"; import React, { useState, useId, InputHTMLAttributes } from "react";
interface FormFieldProps extends InputHTMLAttributes<HTMLInputElement> { interface FormFieldProps
extends Omit<InputHTMLAttributes<HTMLInputElement>, "value" | "onChange"> {
title: string; title: string;
value: string | number;
placeholder?: string; placeholder?: string;
value: string;
handleChangeText: (value: string) => void; handleChangeText: (value: string) => void;
} }
const FormField = ({ const FormField: React.FC<FormFieldProps> = ({
title, title,
placeholder,
value, value,
placeholder,
handleChangeText, handleChangeText,
type,
...props ...props
}: FormFieldProps) => { }) => {
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
const isPasswordField = title.toLowerCase().includes("password"); const inputId = useId();
const inputId = `input-${title.replace(/\s+/g, "-").toLowerCase()}`; const isPasswordField =
type === "password" || title.toLowerCase().includes("password");
const inputType = isPasswordField
? showPassword
? "text"
: "password"
: type || "text";
return ( return (
<div className="w-full"> <div className="w-full">
@ -31,9 +40,10 @@ const FormField = ({
<div className="h-16 px-4 bg-[#D2DFF0] rounded-3xl flex items-center justify-between"> <div className="h-16 px-4 bg-[#D2DFF0] rounded-3xl flex items-center justify-between">
<input <input
id={inputId} id={inputId}
type={isPasswordField && !showPassword ? "password" : "text"} type={inputType}
value={value} value={value}
placeholder={placeholder} placeholder={placeholder || `Enter ${title.toLowerCase()}`}
autoComplete={isPasswordField ? "current-password" : "on"}
onChange={(e) => handleChangeText(e.target.value)} onChange={(e) => handleChangeText(e.target.value)}
className="flex-1 bg-transparent outline-none border-none text-blue-950 text-[16px] font-inherit" className="flex-1 bg-transparent outline-none border-none text-blue-950 text-[16px] font-inherit"
{...props} {...props}
@ -43,8 +53,9 @@ const FormField = ({
<button <button
type="button" type="button"
onClick={() => setShowPassword((prev) => !prev)} onClick={() => setShowPassword((prev) => !prev)}
aria-pressed={showPassword}
aria-label={showPassword ? "Hide password" : "Show password"} aria-label={showPassword ? "Hide password" : "Show password"}
className="ml-2 text-gray-600 hover:text-gray-800 focus:outline-none font-montserrat font-medium text-[16px] bg-none border-none" className="ml-2 text-gray-600 hover:text-gray-800 focus:outline-none font-montserrat font-medium text-[16px]"
> >
{showPassword ? "Hide" : "Show"} {showPassword ? "Hide" : "Show"}
</button> </button>

View File

@ -9,6 +9,7 @@
"lint": "next lint" "lint": "next lint"
}, },
"dependencies": { "dependencies": {
"@capacitor/android": "^7.4.2",
"@capacitor/core": "^7.4.2", "@capacitor/core": "^7.4.2",
"@radix-ui/react-avatar": "^1.1.10", "@radix-ui/react-avatar": "^1.1.10",
"@radix-ui/react-label": "^2.1.7", "@radix-ui/react-label": "^2.1.7",

14
types/auth.d.ts vendored
View File

@ -8,13 +8,17 @@ export interface UserData {
} }
export interface RegisterForm { export interface RegisterForm {
name: string; full_name: string;
institution: string; username: string;
sscRoll: string;
hscRoll: string;
email: string; email: string;
phone: string;
password: string; password: string;
phone_number: string;
ssc_roll: number;
ssc_board: string;
hsc_roll: number;
hsc_board: string;
college: string;
preparation_unit: "Science" | "Arts" | "Commerce" | string;
} }
export interface LoginForm { export interface LoginForm {