mirror of
https://github.com/ramvignesh-b/pi-ku.git
synced 2026-05-04 08:56:52 +00:00
feat: implement registration page with form validation and add custom typography fonts
This commit is contained in:
@@ -5,6 +5,11 @@
|
||||
"": {
|
||||
"name": "frontend",
|
||||
"dependencies": {
|
||||
"@fontsource-variable/jost": "^5.2.8",
|
||||
"@fontsource-variable/playfair-display": "^5.2.8",
|
||||
"@fontsource-variable/playwrite-hr-lijeva": "^5.2.7",
|
||||
"@fontsource/cutive-mono": "^5.2.8",
|
||||
"@fontsource/knewave": "^5.2.7",
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
"@phosphor-icons/react": "^2.1.10",
|
||||
"@tailwindcss/vite": "^4.2.2",
|
||||
@@ -53,6 +58,16 @@
|
||||
|
||||
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],
|
||||
|
||||
"@fontsource-variable/jost": ["@fontsource-variable/jost@5.2.8", "", {}, "sha512-+VDDHpbhgZ9A8KeHb7/LUMRR1LILVKIscNhVRSDzn3tFXoi1mFA/OhO8CZL/u2OujoGjZANjOdUZIgaxclxyjw=="],
|
||||
|
||||
"@fontsource-variable/playfair-display": ["@fontsource-variable/playfair-display@5.2.8", "", {}, "sha512-ZzVIXPOrL85yyOvZYoBzUszIJM+xKkHqni4IYn2CVLaGQQdJR8sBeC8yFNgjxSJ7ludTwta8qpULeOFuk5X75A=="],
|
||||
|
||||
"@fontsource-variable/playwrite-hr-lijeva": ["@fontsource-variable/playwrite-hr-lijeva@5.2.7", "", {}, "sha512-cQqbD8HHZDpiKdtgwUxgwAY76TC+GI9iZOxHSW0XkV/L8lA0X18z1wzR+J8yv9XZQYgLJ5WfzBGwzMSLnSLdPA=="],
|
||||
|
||||
"@fontsource/cutive-mono": ["@fontsource/cutive-mono@5.2.8", "", {}, "sha512-Y8PKAYfbpl9Empbb1HZBoirlj4W7RtU+G4EhvX27pHzO6RE1sO0I1ElZQH5DMCTS+MSJkMmQT33sJ0+Ji9U8eQ=="],
|
||||
|
||||
"@fontsource/knewave": ["@fontsource/knewave@5.2.7", "", {}, "sha512-uzx8jgcTiQgAwKvQ/hWdX7lOQPwS+K74Eij/WCVzYvAkCX7GRTnWnbxXXx0XsKR6UIN16kH/u40LW4K8aHJb1w=="],
|
||||
|
||||
"@hookform/resolvers": ["@hookform/resolvers@5.2.2", "", { "dependencies": { "@standard-schema/utils": "^0.3.0" }, "peerDependencies": { "react-hook-form": "^7.55.0" } }, "sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA=="],
|
||||
|
||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource-variable/jost": "^5.2.8",
|
||||
"@fontsource-variable/playfair-display": "^5.2.8",
|
||||
"@fontsource-variable/playwrite-hr-lijeva": "^5.2.7",
|
||||
"@fontsource/cutive-mono": "^5.2.8",
|
||||
"@fontsource/knewave": "^5.2.7",
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
"@phosphor-icons/react": "^2.1.10",
|
||||
"@tailwindcss/vite": "^4.2.2",
|
||||
|
||||
@@ -167,7 +167,7 @@
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -4.5px;
|
||||
border: 5px solid transparent;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
|
||||
import Home from './pages/Home';
|
||||
import Register from './pages/Register';
|
||||
import VerifyEmail from './pages/VerifyEmail';
|
||||
import Activate from './pages/Activate';
|
||||
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
|
||||
import Activate from "./pages/Activate";
|
||||
import Home from "./pages/Home";
|
||||
import Register from "./pages/Register";
|
||||
import VerifyEmail from "./pages/VerifyEmail";
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
@@ -10,7 +10,7 @@ export default function App() {
|
||||
<div className="min-h-screen bg-base-200 p-8 flex items-center justify-center">
|
||||
<Routes>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/register" element={<Register />} />
|
||||
<Route path="/onboard" element={<Register />} />
|
||||
<Route path="/verify-email" element={<VerifyEmail />} />
|
||||
<Route path="/activate/:uidb64/:token" element={<Activate />} />
|
||||
<Route path="*" element={<Navigate to="/" replace />} />
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { DotIcon } from "@phosphor-icons/react"
|
||||
import "@fontsource/knewave"
|
||||
|
||||
export default function Logo() {
|
||||
|
||||
return (
|
||||
<div className="flex items-baseline leading-none align-baseline">
|
||||
<span className="text-2xl font-light font-logo text-accent"> Pi</span>
|
||||
<DotIcon weight="fill" size={12} className="text-accent translate-y-px" />
|
||||
<span className="text-2xl font-light font-logo text-accent ml-0.5">Ku</span>
|
||||
<DotIcon weight="fill" size={12} className="text-accent translate-y-px" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+17
-3
@@ -14,8 +14,8 @@
|
||||
--color-primary-content: #c8b890;
|
||||
--color-secondary: #2a1e13;
|
||||
--color-secondary-content: #e8d5b0;
|
||||
--color-accent: #3d2e1e;
|
||||
--color-accent-content: #c8903a;
|
||||
--color-accent: #c8903a;
|
||||
--color-accent-content: #3d2e1e;
|
||||
--color-neutral: #2e2820;
|
||||
--color-neutral-content: oklch(98% 0.016 73.684);
|
||||
--color-info: #2a3040;
|
||||
@@ -24,7 +24,7 @@
|
||||
--color-success-content: #8aaa8a;
|
||||
--color-warning: #4a3010;
|
||||
--color-warning-content: #d4a050;
|
||||
--color-error: #3d1e1a;
|
||||
--color-error: #3d1e1f;
|
||||
--color-error-content: #c07060;
|
||||
--radius-selector: 1rem;
|
||||
--radius-field: 0rem;
|
||||
@@ -35,3 +35,17 @@
|
||||
--depth: 0;
|
||||
--noise: 0;
|
||||
}
|
||||
|
||||
@theme {
|
||||
--font-logo: "Knewave", system-ui;
|
||||
--font-display: "Playwrite HR Lijeva Variable", cursive;
|
||||
--font-sans: "Jost Variable", sans-serif;
|
||||
--font-serif: "Playfair Display Variable", serif;
|
||||
--color-glass-bg: rgba(35, 30, 24, 0.4);
|
||||
--shadow-warm: 0 20px 50px -12px rgba(42, 30, 19, 0.5);
|
||||
--radius-xl: 1.5rem;
|
||||
}
|
||||
|
||||
.glass-card {
|
||||
@apply bg-glass-bg backdrop-blur-xl border border-white/5 shadow-warm rounded-xl;
|
||||
}
|
||||
|
||||
+12
-6
@@ -1,10 +1,16 @@
|
||||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import './index.css'
|
||||
import App from './App.tsx'
|
||||
import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import "./index.css";
|
||||
import "@fontsource-variable/playwrite-hr-lijeva/wght.css";
|
||||
import "@fontsource-variable/jost/wght.css";
|
||||
import "@fontsource-variable/playfair-display/wght.css";
|
||||
import App from "./App.tsx";
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
const root = document.getElementById("root");
|
||||
if (root) {
|
||||
createRoot(root).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import Logo from "../components/Logo";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Pi. Ku.</h1>
|
||||
<Logo/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,112 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { InfoIcon } from "@phosphor-icons/react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
import Logo from "../components/Logo";
|
||||
|
||||
// validation logic
|
||||
const registerSchema = z
|
||||
.object({
|
||||
email: z.email("Please enter a valid email"),
|
||||
password: z
|
||||
.string()
|
||||
.check(z.minLength(8, "Password must be at least 8 characters")),
|
||||
confirm_password: z.string(),
|
||||
})
|
||||
.refine((data) => data.password === data.confirm_password, {
|
||||
message: "Passwords don't match",
|
||||
path: ["confirm_password"],
|
||||
});
|
||||
|
||||
type RegisterInputs = z.infer<typeof registerSchema>;
|
||||
|
||||
export default function Register() {
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm<RegisterInputs>({
|
||||
resolver: zodResolver(registerSchema),
|
||||
});
|
||||
|
||||
const onSubmit = (data: RegisterInputs) => {
|
||||
console.log("Form Data:", data);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Register</h1>
|
||||
<div className="glass-card w-full max-w-sm p-2 transition-all duration-500 hover:shadow-2xl">
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="card-body gap-4">
|
||||
<h2 className="card-title font-display text-2xl font-bold justify-center text-primary tracking-tight">
|
||||
Create a <Logo /> Account
|
||||
</h2>
|
||||
|
||||
<div className="form-control">
|
||||
<label htmlFor="email" className="label font-bold font-display py-1">
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
{...register("email")}
|
||||
type="email"
|
||||
placeholder="you@email.com"
|
||||
className={`input input-bordered focus:input-primary ${errors.email ? "input-error" : ""}`}
|
||||
/>
|
||||
{errors.email && (
|
||||
<p className="text-error-content text-xs mt-1">{errors.email.message}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="form-control">
|
||||
<label htmlFor="password" className="label font-bold font-display py-1">
|
||||
Password
|
||||
</label>
|
||||
<input
|
||||
{...register("password")}
|
||||
type="password"
|
||||
placeholder="••••••••"
|
||||
className={`input input-bordered focus:input-primary ${errors.password ? "input-error" : ""}`}
|
||||
/>
|
||||
{errors.password && (
|
||||
<p className="text-error-content text-xs mt-1">{errors.password.message}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Confirm Pass */}
|
||||
<div className="form-control">
|
||||
<label htmlFor="confirm_password" className="label font-bold font-display py-1">
|
||||
Confirm Password
|
||||
</label>
|
||||
<input
|
||||
{...register("confirm_password")}
|
||||
type="password"
|
||||
placeholder="••••••••"
|
||||
className={`input input-bordered focus:input-primary ${errors.confirm_password ? "input-error" : ""}`}
|
||||
/>
|
||||
{errors.confirm_password && (
|
||||
<p className="text-error-content text-xs mt-1">
|
||||
{errors.confirm_password.message}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Warning */}
|
||||
<div className="bg-warning/10 border-l-2 border-warning p-3 rounded-r-md flex gap-2">
|
||||
<InfoIcon
|
||||
size={20}
|
||||
weight="duotone"
|
||||
className="text-warning mt-0.5 shrink-0"
|
||||
/>
|
||||
<p className="text-sm text-warning-content font-medium opacity-90">
|
||||
Choose a password you won't forget. <br />
|
||||
<span className="font-semibold underline">There is no reset.</span> If you lose it, your letters cannot be recovered.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="card-actions mt-4">
|
||||
<button type="submit" className="btn btn-primary w-full shadow-lg">
|
||||
Register
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user