because I got bored of customising my CV for every job
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor(client): reorganize auth components and queries

+90 -97
+6 -4
apps/client/src/features/auth/components/AuthForm.tsx
··· 1 - import type { ReactNode } from "react"; 1 + import type { FormEvent, ReactNode } from "react"; 2 2 import { ServerStatusIndicator } from "@/components/ServerStatusIndicator"; 3 3 4 4 type AuthFormProps = { 5 5 title: string; 6 6 children: ReactNode; 7 + submit: (e: FormEvent) => void | Promise<void>; 7 8 }; 8 9 9 - export default function AuthForm({ title, children }: AuthFormProps) { 10 + export default function AuthForm({ title, children, submit }: AuthFormProps) { 10 11 return ( 11 12 <main className="min-h-dvh grid place-items-center p-4"> 12 13 <div className="w-full max-w-md rounded-lg bg-ctp-crust/40 p-6 shadow"> ··· 14 15 <h1 className="text-2xl font-semibold">{title}</h1> 15 16 <ServerStatusIndicator compact /> 16 17 </div> 17 - 18 - {children} 18 + <form className="space-y-4" onSubmit={submit}> 19 + {children} 20 + </form> 19 21 </div> 20 22 </main> 21 23 );
+32 -37
apps/client/src/features/auth/components/LoginForm.tsx
··· 1 + import { Button, TextInput } from "@cv/ui"; 1 2 import { useState } from "react"; 2 3 import { Link } from "react-router-dom"; 3 4 import { useLogin } from "@/hooks/useAuth"; 4 - import Button from "@/ui/Button"; 5 - import TextInput from "@/ui/TextInput"; 6 5 import AuthForm from "./AuthForm"; 7 6 8 7 export default function LoginForm() { 9 8 const [email, setEmail] = useState(""); 10 9 const [password, setPassword] = useState(""); 11 - const [loginMutation, { loading, error }] = useLogin(); 10 + const { mutate, isPending, error } = useLogin(); 12 11 13 12 const handleSubmit = (e: React.FormEvent) => { 14 13 e.preventDefault(); 15 - loginMutation({ 16 - variables: { 17 - email, 18 - password, 19 - }, 14 + mutate({ 15 + email, 16 + password, 20 17 }); 21 18 }; 22 19 23 20 return ( 24 - <AuthForm title="Welcome back"> 25 - <form className="space-y-4" onSubmit={handleSubmit}> 26 - <TextInput 27 - label="Email" 28 - type="email" 29 - placeholder="you@example.com" 30 - value={email} 31 - onChange={setEmail} 32 - error={error?.message || undefined} 33 - /> 34 - <TextInput 35 - label="Password" 36 - type="password" 37 - placeholder="••••••••" 38 - value={password} 39 - onChange={setPassword} 40 - /> 41 - <Button className="w-full" type="submit" disabled={loading}> 42 - {loading ? "Signing in..." : "Sign in"} 43 - </Button> 44 - <p className="mt-4 text-center text-sm text-ctp-subtext0"> 45 - No account yet?{" "} 46 - <Link to="/auth/register"> 47 - <Button variant="ghost" size="sm"> 48 - Register 49 - </Button> 50 - </Link> 51 - </p> 52 - </form> 21 + <AuthForm title="Welcome back" submit={handleSubmit}> 22 + <TextInput 23 + label="Email" 24 + type="email" 25 + placeholder="you@example.com" 26 + value={email} 27 + onChange={setEmail} 28 + error={(error as Error)?.message || undefined} 29 + /> 30 + <TextInput 31 + label="Password" 32 + type="password" 33 + placeholder="••••••••" 34 + value={password} 35 + onChange={setPassword} 36 + /> 37 + <Button className="w-full" type="submit" disabled={isPending}> 38 + {isPending ? "Signing in..." : "Sign in"} 39 + </Button> 40 + <p className="mt-4 text-center text-sm text-ctp-subtext0"> 41 + No account yet?{" "} 42 + <Link to="/auth/register"> 43 + <Button variant="ghost" size="sm"> 44 + Register 45 + </Button> 46 + </Link> 47 + </p> 53 48 </AuthForm> 54 49 ); 55 50 }
+39 -44
apps/client/src/features/auth/components/RegisterForm.tsx
··· 1 + import { Button, TextInput } from "@cv/ui"; 1 2 import { useState } from "react"; 2 3 import { Link } from "react-router-dom"; 3 4 import { useRegister } from "@/hooks/useAuth"; 4 - import Button from "@/ui/Button"; 5 - import TextInput from "@/ui/TextInput"; 6 5 import AuthForm from "./AuthForm"; 7 6 8 7 export default function RegisterForm() { 9 8 const [name, setName] = useState(""); 10 9 const [email, setEmail] = useState(""); 11 10 const [password, setPassword] = useState(""); 12 - const [register, { loading, error }] = useRegister(); 11 + const { mutate, isPending, error } = useRegister(); 13 12 14 13 const handleSubmit = (e: React.FormEvent) => { 15 14 e.preventDefault(); 16 - register({ 17 - variables: { 18 - name, 19 - email, 20 - password, 21 - }, 15 + mutate({ 16 + name, 17 + email, 18 + password, 22 19 }); 23 20 }; 24 21 25 22 return ( 26 - <AuthForm title="Create account"> 27 - <form className="space-y-4" onSubmit={handleSubmit}> 28 - <TextInput 29 - label="Name" 30 - placeholder="Jane Doe" 31 - value={name} 32 - onChange={setName} 33 - /> 34 - <TextInput 35 - label="Email" 36 - type="email" 37 - placeholder="you@example.com" 38 - value={email} 39 - onChange={setEmail} 40 - error={error?.message || undefined} 41 - /> 42 - <TextInput 43 - label="Password" 44 - type="password" 45 - placeholder="••••••••" 46 - value={password} 47 - onChange={setPassword} 48 - /> 49 - <Button className="w-full" type="submit" disabled={loading}> 50 - {loading ? "Creating account..." : "Create account"} 51 - </Button> 52 - <p className="mt-4 text-center text-sm text-ctp-subtext0"> 53 - Already have an account?{" "} 54 - <Link to="/auth/login"> 55 - <Button variant="ghost" size="sm"> 56 - Login 57 - </Button> 58 - </Link> 59 - </p> 60 - </form> 23 + <AuthForm title="Create account" submit={handleSubmit}> 24 + <TextInput 25 + label="Name" 26 + placeholder="Jane Doe" 27 + value={name} 28 + onChange={setName} 29 + /> 30 + <TextInput 31 + label="Email" 32 + type="email" 33 + placeholder="you@example.com" 34 + value={email} 35 + onChange={setEmail} 36 + error={(error as Error)?.message || undefined} 37 + /> 38 + <TextInput 39 + label="Password" 40 + type="password" 41 + placeholder="••••••••" 42 + value={password} 43 + onChange={setPassword} 44 + /> 45 + <Button className="w-full" type="submit" disabled={isPending}> 46 + {isPending ? "Creating account..." : "Create account"} 47 + </Button> 48 + <p className="mt-4 text-center text-sm text-ctp-subtext0"> 49 + Already have an account?{" "} 50 + <Link to="/auth/login"> 51 + <Button variant="ghost" size="sm"> 52 + Login 53 + </Button> 54 + </Link> 55 + </p> 61 56 </AuthForm> 62 57 ); 63 58 }
+13 -12
apps/client/src/features/auth/queries/auth.graphql
··· 1 + fragment AuthFields on AuthResponse { 2 + access_token 3 + refresh_token 4 + expires_at 5 + user { 6 + id 7 + email 8 + name 9 + } 10 + } 11 + 1 12 mutation Login($email: String!, $password: String!) { 2 13 login(email: $email, password: $password) { 3 - access_token 4 - user { 5 - id 6 - email 7 - name 8 - } 14 + ...AuthFields 9 15 } 10 16 } 11 17 12 18 mutation Register($name: String!, $email: String!, $password: String!) { 13 19 register(name: $name, email: $email, password: $password) { 14 - access_token 15 - user { 16 - id 17 - email 18 - name 19 - } 20 + ...AuthFields 20 21 } 21 22 }