-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #90 from square-story/frontend
Frontend
- Loading branch information
Showing
15 changed files
with
706 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import axios from 'axios' | ||
|
||
export const axiosInstance = axios.create({ | ||
baseURL: 'http://localhost:3000', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
withCredentials: true, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import * as React from 'react' | ||
import { Eye, EyeOff } from 'lucide-react'; | ||
import { cn } from '@/lib/utils' | ||
import { Button } from './ui/button' | ||
|
||
type PasswordInputProps = Omit< | ||
React.InputHTMLAttributes<HTMLInputElement>, | ||
'type' | ||
> | ||
|
||
const PasswordInput = React.forwardRef<HTMLInputElement, PasswordInputProps>( | ||
({ className, disabled, ...props }, ref) => { | ||
const [showPassword, setShowPassword] = React.useState(false) | ||
return ( | ||
<div className={cn('relative rounded-md', className)}> | ||
<input | ||
type={showPassword ? 'text' : 'password'} | ||
className='flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50' | ||
ref={ref} | ||
disabled={disabled} | ||
{...props} | ||
/> | ||
<Button | ||
type='button' | ||
size='icon' | ||
variant='ghost' | ||
disabled={disabled} | ||
className='absolute right-1 top-1/2 h-6 w-6 -translate-y-1/2 rounded-md text-muted-foreground' | ||
onClick={() => setShowPassword((prev) => !prev)} | ||
> | ||
{showPassword ? <Eye size={18} /> : <EyeOff size={18} />} | ||
</Button> | ||
</div> | ||
) | ||
} | ||
) | ||
PasswordInput.displayName = 'PasswordInput' | ||
|
||
export { PasswordInput } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
import * as React from 'react' | ||
import { | ||
Controller, | ||
ControllerProps, | ||
FieldPath, | ||
FieldValues, | ||
FormProvider, | ||
useFormContext, | ||
} from 'react-hook-form' | ||
import * as LabelPrimitive from '@radix-ui/react-label' | ||
import { Slot } from '@radix-ui/react-slot' | ||
import { cn } from '@/lib/utils' | ||
import { Label } from '@/components/ui/label' | ||
|
||
const Form = FormProvider | ||
|
||
type FormFieldContextValue< | ||
TFieldValues extends FieldValues = FieldValues, | ||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, | ||
> = { | ||
name: TName | ||
} | ||
|
||
const FormFieldContext = React.createContext<FormFieldContextValue>( | ||
{} as FormFieldContextValue | ||
) | ||
|
||
const FormField = < | ||
TFieldValues extends FieldValues = FieldValues, | ||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>, | ||
>({ | ||
...props | ||
}: ControllerProps<TFieldValues, TName>) => { | ||
return ( | ||
<FormFieldContext.Provider value={{ name: props.name }}> | ||
<Controller {...props} /> | ||
</FormFieldContext.Provider> | ||
) | ||
} | ||
|
||
const useFormField = () => { | ||
const fieldContext = React.useContext(FormFieldContext) | ||
const itemContext = React.useContext(FormItemContext) | ||
const { getFieldState, formState } = useFormContext() | ||
|
||
const fieldState = getFieldState(fieldContext.name, formState) | ||
|
||
if (!fieldContext) { | ||
throw new Error('useFormField should be used within <FormField>') | ||
} | ||
|
||
const { id } = itemContext | ||
|
||
return { | ||
id, | ||
name: fieldContext.name, | ||
formItemId: `${id}-form-item`, | ||
formDescriptionId: `${id}-form-item-description`, | ||
formMessageId: `${id}-form-item-message`, | ||
...fieldState, | ||
} | ||
} | ||
|
||
type FormItemContextValue = { | ||
id: string | ||
} | ||
|
||
const FormItemContext = React.createContext<FormItemContextValue>( | ||
{} as FormItemContextValue | ||
) | ||
|
||
const FormItem = React.forwardRef< | ||
HTMLDivElement, | ||
React.HTMLAttributes<HTMLDivElement> | ||
>(({ className, ...props }, ref) => { | ||
const id = React.useId() | ||
|
||
return ( | ||
<FormItemContext.Provider value={{ id }}> | ||
<div ref={ref} className={cn('space-y-2', className)} {...props} /> | ||
</FormItemContext.Provider> | ||
) | ||
}) | ||
FormItem.displayName = 'FormItem' | ||
|
||
const FormLabel = React.forwardRef< | ||
React.ElementRef<typeof LabelPrimitive.Root>, | ||
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> | ||
>(({ className, ...props }, ref) => { | ||
const { error, formItemId } = useFormField() | ||
|
||
return ( | ||
<Label | ||
ref={ref} | ||
className={cn(error && 'text-destructive', className)} | ||
htmlFor={formItemId} | ||
{...props} | ||
/> | ||
) | ||
}) | ||
FormLabel.displayName = 'FormLabel' | ||
|
||
const FormControl = React.forwardRef< | ||
React.ElementRef<typeof Slot>, | ||
React.ComponentPropsWithoutRef<typeof Slot> | ||
>(({ ...props }, ref) => { | ||
const { error, formItemId, formDescriptionId, formMessageId } = useFormField() | ||
|
||
return ( | ||
<Slot | ||
ref={ref} | ||
id={formItemId} | ||
aria-describedby={ | ||
!error | ||
? `${formDescriptionId}` | ||
: `${formDescriptionId} ${formMessageId}` | ||
} | ||
aria-invalid={!!error} | ||
{...props} | ||
/> | ||
) | ||
}) | ||
FormControl.displayName = 'FormControl' | ||
|
||
const FormDescription = React.forwardRef< | ||
HTMLParagraphElement, | ||
React.HTMLAttributes<HTMLParagraphElement> | ||
>(({ className, ...props }, ref) => { | ||
const { formDescriptionId } = useFormField() | ||
|
||
return ( | ||
<p | ||
ref={ref} | ||
id={formDescriptionId} | ||
className={cn('text-[0.8rem] text-muted-foreground', className)} | ||
{...props} | ||
/> | ||
) | ||
}) | ||
FormDescription.displayName = 'FormDescription' | ||
|
||
const FormMessage = React.forwardRef< | ||
HTMLParagraphElement, | ||
React.HTMLAttributes<HTMLParagraphElement> | ||
>(({ className, children, ...props }, ref) => { | ||
const { error, formMessageId } = useFormField() | ||
const body = error ? String(error?.message) : children | ||
|
||
if (!body) { | ||
return null | ||
} | ||
|
||
return ( | ||
<p | ||
ref={ref} | ||
id={formMessageId} | ||
className={cn('text-[0.8rem] font-medium text-destructive', className)} | ||
{...props} | ||
> | ||
{body} | ||
</p> | ||
) | ||
}) | ||
FormMessage.displayName = 'FormMessage' | ||
|
||
export { | ||
useFormField, | ||
Check warning on line 167 in frontend/src/components/ui/form.tsx
|
||
Form, | ||
FormItem, | ||
FormLabel, | ||
FormControl, | ||
FormDescription, | ||
FormMessage, | ||
FormField, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { useTheme } from "next-themes" | ||
import { Toaster as Sonner, ToasterProps } from "sonner" | ||
|
||
const Toaster = ({ ...props }: ToasterProps) => { | ||
const { theme = "system" } = useTheme() | ||
|
||
return ( | ||
<Sonner | ||
theme={theme as ToasterProps["theme"]} | ||
className="toaster group" | ||
toastOptions={{ | ||
classNames: { | ||
toast: | ||
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg", | ||
description: "group-[.toast]:text-muted-foreground", | ||
actionButton: | ||
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground font-medium", | ||
cancelButton: | ||
"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground font-medium", | ||
}, | ||
}} | ||
{...props} | ||
/> | ||
) | ||
} | ||
|
||
export { Toaster } |
This file was deleted.
Oops, something went wrong.
66 changes: 66 additions & 0 deletions
66
frontend/src/components/user/auth/components/FormLayout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { Separator } from "@/components/ui/separator" | ||
import { UserAuthForm } from "./user-auth-form" | ||
import Button from "@/components/ui/button" | ||
import { Github } from "lucide-react" | ||
import { useState } from "react" | ||
|
||
|
||
export const FormLayout = () => { | ||
|
||
const [authState, setAuthState] = useState<'login' | 'register'>('login'); | ||
|
||
return ( | ||
<div className='lg:p-8'> | ||
<div className='mx-auto flex w-full flex-col justify-center space-y-2 sm:w-[350px]'> | ||
<div className='flex flex-col space-y-2 text-left'> | ||
<h1 className='text-2xl font-semibold tracking-tight'>{authState === 'login' ? "Welcome Back!" : "Create an Account"}</h1> | ||
<p className='text-sm text-muted-foreground'> | ||
{authState === 'login' ? "Please enter your email and password to log in." : "Please fill in the details to create your account."} | ||
</p> | ||
</div> | ||
<UserAuthForm | ||
authState={authState} | ||
onStateChange={setAuthState} | ||
/> | ||
<div className="relative"> | ||
<div className="absolute inset-0 flex items-center"> | ||
<Separator /> | ||
</div> | ||
<div className="relative flex justify-center text-xs uppercase"> | ||
<span className="bg-background px-2 text-muted-foreground"> | ||
Or continue with | ||
</span> | ||
</div> | ||
</div> | ||
|
||
<div className="flex gap-2 "> | ||
<Button variant="outline" className="w-full"> | ||
<svg className="mr-2 h-4 w-4" viewBox="0 0 24 24"> | ||
<path | ||
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" | ||
fill="#4285F4" | ||
/> | ||
<path | ||
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" | ||
fill="#34A853" | ||
/> | ||
<path | ||
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" | ||
fill="#FBBC05" | ||
/> | ||
<path | ||
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" | ||
fill="#EA4335" | ||
/> | ||
</svg> | ||
</Button> | ||
<Button variant="outline" className="w-full"> | ||
<Github className="mr-2 h-4 w-4" /> | ||
Github | ||
</Button> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
} |
19 changes: 19 additions & 0 deletions
19
frontend/src/components/user/auth/components/SideLayout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { useTheme } from "../../common/theme-provider" | ||
import LightLogo from '@/assets/Logo Light.svg' | ||
import DarkLogo from '@/assets/Logo Dark.svg' | ||
|
||
export const SideLayout = () => { | ||
const { theme } = useTheme() | ||
return ( | ||
<div className='relative hidden h-full flex-col bg-muted p-10 text-white dark:border-r lg:flex'> | ||
<div className='absolute inset-0 bg-zinc-900' /> | ||
<div className='relative z-20 flex items-center text-lg font-medium'> | ||
<img | ||
src={theme == 'light' ? LightLogo : DarkLogo} | ||
className='mr-2 h-20 w-20' | ||
alt='Inker' | ||
/> | ||
</div> | ||
</div> | ||
) | ||
} |
Oops, something went wrong.