-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
40 changed files
with
664 additions
and
5 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,40 @@ | ||
import { Button } from "@/components/ui/button"; | ||
import PatientForm from "@/components/forms/PatientForm"; | ||
import Image from "next/image"; | ||
import Link from "next/link"; | ||
|
||
export default function Home() { | ||
return ( | ||
<div className='flex h-screen max-h-screen '> | ||
<section className='remove-scrollbar container my-auto'></section> | ||
{/* TODO: OTP Verification | PassKeyModel */} | ||
<section className='remove-scrollbar container my-auto'> | ||
<div className='sub-container max-w-[496px]'> | ||
<Image | ||
src={"/assets/icons/logo-full.svg"} | ||
height={1000} | ||
width={1000} | ||
alt='patient' | ||
className='mb-12 h-10 w-fit' | ||
/> | ||
|
||
<PatientForm /> | ||
|
||
<div className='text-14-regular mt-20 flex justify-between'> | ||
<p className='justify-items-end text-dark-600 xl:text-left'> | ||
© 2024 CarePlus | ||
</p> | ||
<Link href={"/?admin=true"} className='text-green-500'> | ||
Admin | ||
</Link> | ||
</div> | ||
</div> | ||
</section> | ||
<Image | ||
src={"/assets/images/onboarding-img.png"} | ||
height={1000} | ||
width={1000} | ||
alt='patient' | ||
className='side-img max-w-[50%]' | ||
/> | ||
</div> | ||
); | ||
} |
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,82 @@ | ||
"use client"; | ||
|
||
import { Control } from "react-hook-form"; | ||
import { | ||
FormControl, | ||
FormDescription, | ||
FormField, | ||
FormItem, | ||
FormLabel, | ||
FormMessage, | ||
} from "./ui/form"; | ||
import { Input } from "./ui/input"; | ||
import { FormFieldType } from "./forms/PatientForm"; | ||
import Image from "next/image"; | ||
|
||
interface CustomProps { | ||
control: Control<any>; | ||
fieldType: FormFieldType; | ||
name: string; | ||
label?: string; | ||
placeholder?: string; | ||
iconSrc?: string; | ||
iconAlt?: string; | ||
disabled?: boolean; | ||
dateFormate?: string; | ||
showTimeSelect?: boolean; | ||
children?: React.ReactNode; | ||
renderSkeleton?: (field: any) => React.ReactNode; | ||
} | ||
|
||
const RenderField = ({ field, props }: { field: any; props: CustomProps }) => { | ||
const { fieldType, iconSrc, iconAlt, placeholder } = props; | ||
switch (fieldType) { | ||
case FormFieldType.INPUT: | ||
return ( | ||
<div className='flex rounded-md border border-dark-500'> | ||
{iconSrc && ( | ||
<Image | ||
src={iconSrc} | ||
height={24} | ||
width={24} | ||
alt={iconAlt || "icon"} | ||
className='ml-2' | ||
/> | ||
)} | ||
|
||
<FormControl> | ||
<Input | ||
placeholder={placeholder} | ||
{...field} | ||
className='shad-input border-0' | ||
/> | ||
</FormControl> | ||
</div> | ||
); | ||
|
||
default: | ||
break; | ||
} | ||
}; | ||
|
||
const CustomFormField = (props: CustomProps) => { | ||
const { control, fieldType, name, label } = props; | ||
return ( | ||
<FormField | ||
control={control} | ||
name={name} | ||
render={({ field }) => ( | ||
<FormItem> | ||
{fieldType !== FormFieldType.CHECKBOX && label && ( | ||
<FormLabel>{label}</FormLabel> | ||
)} | ||
|
||
<RenderField field={field} props={props} /> | ||
<FormMessage className='shad-error' /> | ||
</FormItem> | ||
)} | ||
/> | ||
); | ||
}; | ||
|
||
export default CustomFormField; |
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,58 @@ | ||
"use client"; | ||
|
||
import { zodResolver } from "@hookform/resolvers/zod"; | ||
import { useForm } from "react-hook-form"; | ||
import { z } from "zod"; | ||
|
||
import { Button } from "@/components/ui/button"; | ||
import { Form } from "@/components/ui/form"; | ||
import CustomFormField from "../CustomFormField"; | ||
|
||
export enum FormFieldType { | ||
INPUT = "input", | ||
TEXTAREA = "textarea", | ||
PHONE_INPUT = "phoneInput", | ||
CHECKBOX = "checkbox", | ||
DATE_PICKER = "datePicker", | ||
SELECT = "select", | ||
SKELETON = "skeleton", | ||
} | ||
|
||
const formSchema = z.object({ | ||
username: z.string().min(2, { | ||
message: "Username must be at least 2 characters.", | ||
}), | ||
}); | ||
|
||
export default function PatientForm() { | ||
const form = useForm<z.infer<typeof formSchema>>({ | ||
resolver: zodResolver(formSchema), | ||
defaultValues: { | ||
username: "", | ||
}, | ||
}); | ||
|
||
function onSubmit(values: z.infer<typeof formSchema>) { | ||
console.log(values); | ||
} | ||
return ( | ||
<Form {...form}> | ||
<form onSubmit={form.handleSubmit(onSubmit)} className='space-y-8'> | ||
<section className='mb-12 space-y-4'> | ||
<h1 className='header'>Hi there 👋</h1> | ||
<p className='text-dark-700'>Schedule your first appointment</p> | ||
</section> | ||
<CustomFormField | ||
fieldType={FormFieldType.INPUT} | ||
control={form.control} | ||
name='name' | ||
label='Full Name' | ||
placeholder='John Doe' | ||
iconSrc='/assets/icons/user.svg' | ||
iconAlt='user' | ||
/> | ||
<Button type='submit'>Submit</Button> | ||
</form> | ||
</Form> | ||
); | ||
} |
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,178 @@ | ||
"use client" | ||
|
||
import * as React from "react" | ||
import * as LabelPrimitive from "@radix-ui/react-label" | ||
import { Slot } from "@radix-ui/react-slot" | ||
import { | ||
Controller, | ||
ControllerProps, | ||
FieldPath, | ||
FieldValues, | ||
FormProvider, | ||
useFormContext, | ||
} from "react-hook-form" | ||
|
||
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-sm 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-sm font-medium text-destructive", className)} | ||
{...props} | ||
> | ||
{body} | ||
</p> | ||
) | ||
}) | ||
FormMessage.displayName = "FormMessage" | ||
|
||
export { | ||
useFormField, | ||
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,25 @@ | ||
import * as React from "react" | ||
|
||
import { cn } from "@/lib/utils" | ||
|
||
export interface InputProps | ||
extends React.InputHTMLAttributes<HTMLInputElement> {} | ||
|
||
const Input = React.forwardRef<HTMLInputElement, InputProps>( | ||
({ className, type, ...props }, ref) => { | ||
return ( | ||
<input | ||
type={type} | ||
className={cn( | ||
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", | ||
className | ||
)} | ||
ref={ref} | ||
{...props} | ||
/> | ||
) | ||
} | ||
) | ||
Input.displayName = "Input" | ||
|
||
export { Input } |
Oops, something went wrong.