Skip to content

Commit d728647

Browse files
authored
Merge pull request #91 from Code-4-Community/aa-frontend-login
#87 - Frontend Login/Signup Page
2 parents af8101a + 5e422ba commit d728647

6 files changed

Lines changed: 558 additions & 89 deletions

File tree

apps/frontend/src/app.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import { AuthProvider } from '@components/AuthProvider';
1111
import { ProtectedRoute } from '@components/ProtectedRoute';
1212
import { AdminRoute } from '@components/AdminRoute';
1313
import { LoginPage } from '@containers/auth/LoginPage';
14-
import { Modal1Page } from '@containers/auth/Modal1Page';
15-
import { Modal2Page } from '@containers/auth/Modal2Page';
14+
import { ConfirmSentEmailPage } from '@containers/auth/ConfirmSentEmailPage';
15+
import { ConfirmRegisteredPage } from '@containers/auth/ConfirmRegisteredPage';
1616
import { DashboardPage } from '@containers/dashboard/DashboardPage';
1717
import { DonorStatsChart } from '@components/DonorStatsChart';
1818

@@ -27,12 +27,12 @@ const router = createBrowserRouter([
2727
element: <LoginPage />,
2828
},
2929
{
30-
path: '/modal1',
31-
element: <Modal1Page />,
30+
path: '/confirm-sent-email',
31+
element: <ConfirmSentEmailPage />,
3232
},
3333
{
34-
path: '/modal2',
35-
element: <Modal2Page />,
34+
path: '/confirm-registered',
35+
element: <ConfirmRegisteredPage />,
3636
},
3737
{
3838
path: '/dashboard',
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
'use client';
2+
3+
import * as React from 'react';
4+
import { cva, type VariantProps } from 'class-variance-authority';
5+
6+
import { cn } from '@lib/utils';
7+
import { Button } from '@components/ui/button';
8+
import { Input } from '@components/ui/input';
9+
import { Textarea } from '@components/ui/textarea';
10+
11+
function InputGroup({ className, ...props }: React.ComponentProps<'div'>) {
12+
return (
13+
<div
14+
data-slot="input-group"
15+
role="group"
16+
className={cn(
17+
'border-input dark:bg-input/30 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-disabled:bg-input/50 dark:has-disabled:bg-input/80 h-8 rounded-lg border transition-colors in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-3 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5 group/input-group relative flex w-full min-w-0 items-center outline-none has-[>textarea]:h-auto',
18+
className,
19+
)}
20+
{...props}
21+
/>
22+
);
23+
}
24+
25+
const inputGroupAddonVariants = cva(
26+
"text-muted-foreground h-auto gap-2 py-1.5 text-sm font-medium group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4 flex cursor-text items-center justify-center select-none",
27+
{
28+
variants: {
29+
align: {
30+
'inline-start':
31+
'pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem] order-first',
32+
'inline-end':
33+
'pr-2 has-[>button]:mr-[-0.3rem] has-[>kbd]:mr-[-0.15rem] order-last',
34+
'block-start':
35+
'px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2 order-first w-full justify-start',
36+
'block-end':
37+
'px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2 order-last w-full justify-start',
38+
},
39+
},
40+
defaultVariants: {
41+
align: 'inline-start',
42+
},
43+
},
44+
);
45+
46+
function InputGroupAddon({
47+
className,
48+
align = 'inline-start',
49+
...props
50+
}: React.ComponentProps<'div'> & VariantProps<typeof inputGroupAddonVariants>) {
51+
return (
52+
<div
53+
role="group"
54+
data-slot="input-group-addon"
55+
data-align={align}
56+
className={cn(inputGroupAddonVariants({ align }), className)}
57+
onClick={(e) => {
58+
if ((e.target as HTMLElement).closest('button')) {
59+
return;
60+
}
61+
e.currentTarget.parentElement?.querySelector('input')?.focus();
62+
}}
63+
{...props}
64+
/>
65+
);
66+
}
67+
68+
const inputGroupButtonVariants = cva(
69+
'gap-2 text-sm flex items-center shadow-none',
70+
{
71+
variants: {
72+
size: {
73+
xs: "h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
74+
sm: '',
75+
'icon-xs':
76+
'size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0',
77+
'icon-sm': 'size-8 p-0 has-[>svg]:p-0',
78+
},
79+
},
80+
defaultVariants: {
81+
size: 'xs',
82+
},
83+
},
84+
);
85+
86+
function InputGroupButton({
87+
className,
88+
type = 'button',
89+
variant = 'ghost',
90+
size = 'xs',
91+
...props
92+
}: Omit<React.ComponentProps<typeof Button>, 'size'> &
93+
VariantProps<typeof inputGroupButtonVariants>) {
94+
return (
95+
<Button
96+
type={type}
97+
data-size={size}
98+
variant={variant}
99+
className={cn(inputGroupButtonVariants({ size }), className)}
100+
{...props}
101+
/>
102+
);
103+
}
104+
105+
function InputGroupText({ className, ...props }: React.ComponentProps<'span'>) {
106+
return (
107+
<span
108+
className={cn(
109+
"text-muted-foreground gap-2 text-sm [&_svg:not([class*='size-'])]:size-4 flex items-center [&_svg]:pointer-events-none",
110+
className,
111+
)}
112+
{...props}
113+
/>
114+
);
115+
}
116+
117+
function InputGroupInput({
118+
className,
119+
...props
120+
}: React.ComponentProps<'input'>) {
121+
return (
122+
<Input
123+
data-slot="input-group-control"
124+
className={cn(
125+
'rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent flex-1',
126+
className,
127+
)}
128+
{...props}
129+
/>
130+
);
131+
}
132+
133+
function InputGroupTextarea({
134+
className,
135+
...props
136+
}: React.ComponentProps<'textarea'>) {
137+
return (
138+
<Textarea
139+
data-slot="input-group-control"
140+
className={cn(
141+
'rounded-none border-0 bg-transparent py-2 shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent flex-1 resize-none',
142+
className,
143+
)}
144+
{...props}
145+
/>
146+
);
147+
}
148+
149+
export {
150+
InputGroup,
151+
InputGroupAddon,
152+
InputGroupButton,
153+
InputGroupText,
154+
InputGroupInput,
155+
InputGroupTextarea,
156+
};

apps/frontend/src/containers/auth/Modal2Page.tsx renamed to apps/frontend/src/containers/auth/ConfirmRegisteredPage.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@ import { useNavigate } from 'react-router-dom';
33
import { HeaderDetailModal } from '@components/HeaderDetailModal/HeaderDetailModal';
44
import bostonBg from '../../assets/green-boston-background.png';
55

6-
export const Modal2Page: React.FC = () => {
6+
export const ConfirmRegisteredPage: React.FC = () => {
77
const navigate = useNavigate();
88

99
const handleSignIn = () => {
10-
navigate('/');
10+
navigate('/login');
1111
};
1212

1313
return (
14-
<div
15-
className="relative min-h-screen w-full bg-cover bg-center bg-no-repeat"
16-
style={{ backgroundImage: `url(${bostonBg})` }}
17-
>
14+
<div className="relative min-h-screen w-full bg-[#007B64]">
15+
<div
16+
className="absolute inset-0 bg-no-repeat bg-cover bg-center opacity-30"
17+
style={{ backgroundImage: `url(${bostonBg})` }}
18+
/>
1819
<HeaderDetailModal
1920
heading="Welcome!"
2021
details={

apps/frontend/src/containers/auth/Modal1Page.tsx renamed to apps/frontend/src/containers/auth/ConfirmSentEmailPage.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@ import { useNavigate } from 'react-router-dom';
33
import { HeaderDetailModal } from '@components/HeaderDetailModal/HeaderDetailModal';
44
import bostonBg from '../../assets/green-boston-background.png';
55

6-
export const Modal1Page: React.FC = () => {
6+
export const ConfirmSentEmailPage: React.FC = () => {
77
const navigate = useNavigate();
88

99
const handleSignIn = () => {
10-
navigate('/');
10+
navigate('/login');
1111
};
1212

1313
return (
14-
<div
15-
className="relative min-h-screen w-full bg-cover bg-center bg-no-repeat"
16-
style={{ backgroundImage: `url(${bostonBg})` }}
17-
>
14+
<div className="relative min-h-screen w-full bg-[#007B64]">
15+
<div
16+
className="absolute inset-0 bg-no-repeat bg-cover bg-center opacity-30"
17+
style={{ backgroundImage: `url(${bostonBg})` }}
18+
/>
1819
<HeaderDetailModal
1920
heading="Check your email"
2021
details="Instructions have been sent to your inbox."

0 commit comments

Comments
 (0)