Skip to content

Commit

Permalink
Merge branch 'main' into feature-authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
KilianBoute authored Jun 12, 2024
2 parents cdf601d + 62e8e16 commit 1275f2a
Show file tree
Hide file tree
Showing 16 changed files with 3,626 additions and 19 deletions.
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"dependencies": {
"@uug-ai/ui": "^1.0.34"
}
}
5 changes: 4 additions & 1 deletion ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"tailwind": "npx tailwindcss -c ./tailwind.config.js -i ./src/index.css -o ./styles/tailwind.css --watch"
},
"dependencies": {
"@hookform/resolvers": "^3.5.0",
"@reduxjs/toolkit": "^2.2.5",
"@uug-ai/ui": "1.0.35",
"autoprefixer": "^10.4.19",
Expand All @@ -21,13 +22,15 @@
"prettier-plugin-tailwindcss": "^0.6.1",
"react": "^18",
"react-dom": "^18",
"react-hook-form": "^7.51.5",
"react-query": "^3.39.3",
"react-redux": "^9.1.2",
"redux": "^5.0.1",
"redux-devtools-extension": "^2.13.9",
"redux-thunk": "^3.1.0",
"tailwindcss": "^3.4.3",
"ts-node": "^10.9.2"
"ts-node": "^10.9.2",
"zod": "^3.23.8"
},
"devDependencies": {
"@chromatic-com/storybook": "^1.3.3",
Expand Down
2 changes: 1 addition & 1 deletion ui/src/app/dashboard/components/AddLocation.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import React from "react";
import { Button } from "@uug-ai/ui";
import { Button } from "../../../components/ui";
import { useAddLocationMutation } from "@/lib/services/locations/locationApi";

const AddLocation = () => {
Expand Down
2 changes: 1 addition & 1 deletion ui/src/app/dashboard/components/AddUser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import React from "react";
import { useAddUserMutation } from "@/lib/services/users/userApi"; // Replace "path/to/addUsersQuery" with the actual path to the module containing the useAddUsersQuery function.
import { Button } from "@uug-ai/ui";
import { Button } from "../../../components/ui";

const AddUser = () => {
const [addUser, { data, error, isLoading }] = useAddUserMutation();
Expand Down
2 changes: 1 addition & 1 deletion ui/src/app/dashboard/components/DeleteUser.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import React from "react";
import { Button } from "@uug-ai/ui";
import { Button } from "../../../components/ui";
import { useDeleteUserMutation } from "@/lib/services/users/userApi";

interface DeleteUserProps {
Expand Down
2 changes: 1 addition & 1 deletion ui/src/app/dashboard/components/LocationInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import { useGetLocationsQuery } from "@/lib/services/locations/locationApi";
import { Box, Text } from "@uug-ai/ui";
import { Box, Text } from "../../../components/ui";
import React from "react";

const LocationInfo = () => {
Expand Down
2 changes: 1 addition & 1 deletion ui/src/app/dashboard/components/UserTable.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { useGetUsersQuery } from "@/lib/services/users/userApi";
import { useGetUsersQuery } from "@/lib/services/users/userApi"
import { Button, Row, Stack, Table, Text } from "../../../components/ui";
import { ColumnProps } from "@uug-ai/ui/lib/components/Table/Table";
import React from "react";
Expand Down
13 changes: 5 additions & 8 deletions ui/src/app/home/page.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import {
Button,
Input,
Gradient,
Socials,

Box,
Gradient,
Stack,
Password,
Row,

} from "../../components/ui";
import React from "react";


export default function Home() {
return <div>Home</div>;
return <Box><Gradient/><Stack>Home</Stack></Box>;
}
88 changes: 88 additions & 0 deletions ui/src/app/onboarding/components/FormComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React, { useEffect, useRef } from "react";
import { useForm, SubmitHandler, FormProvider, useFormContext } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { Box, Text, Input, Button, Logo } from "../../../components/ui";
import { schema } from "./FormSchema";
import { onSubmitAction } from "./FormSubmit";
import { FormData } from "./Types";

interface FormFieldProps {
name: keyof FormData;
label: string;
description?: string;
placeholder?: string;
type?: string;
}

const FormField: React.FC<FormFieldProps> = ({ name, label, description, placeholder, type = "text" }) => {
const { register, formState: { errors } } = useFormContext<FormData>();
return (
<Box className="mb-4">
<Text as="label" weight="semibold" className="mb-1">
{label}
</Text>
<Input {...register(name)} type={type} placeholder={placeholder} className="bg-white" />
{errors[name] && <p>{(errors[name]?.message as string) || ''}</p>}
{description && <p className="text-sm text-gray-500">{description}</p>}
</Box>
);
};

const FormComponent: React.FC<{ videoFile: Blob | null; onSubmit: SubmitHandler<FormData> }> = ({ videoFile, onSubmit }) => {
const methods = useForm<FormData>({
resolver: zodResolver(schema),
defaultValues: {
firstName: "",
lastName: "",
email: "",
phoneNumber: "",
dateOfBirth: "",
video: undefined,
},
});

const formRef = useRef<HTMLFormElement>(null);

useEffect(() => {
if (videoFile) {
methods.setValue("video", videoFile);
}
}, [videoFile, methods]);

const handleFormSubmit = (data: FormData) => {
console.log("handleFormSubmit called with data:", data);
if (videoFile) {
onSubmit({ ...data, video: videoFile });
} else {
console.error("Video file is required.");
}
};

return (
<Box>
<Logo />
<FormProvider {...methods}>
<form
ref={formRef}
className="space-y-8"
onSubmit={(evt) => {
evt.preventDefault();
methods.handleSubmit(handleFormSubmit)(evt);
}}
>
<FormField name="firstName" label="First Name" placeholder="First Name" description="Your first name." />
<FormField name="lastName" label="Last Name" placeholder="Last Name" description="Your last name." />
<FormField name="email" label="Email" placeholder="E-Mail" description="Your email address." />
<FormField name="phoneNumber" label="Phone Number" placeholder="Phone Number" description="Your phone number." />
<FormField name="dateOfBirth" label="Date of Birth" type="date" placeholder="Date of Birth" description="Your date of birth." />
<Button type="submit" variant="solid" width="third">
Register
</Button>
</form>
</FormProvider>
</Box>
);
};

export default FormComponent;
12 changes: 12 additions & 0 deletions ui/src/app/onboarding/components/FormSchema.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { z } from "zod";

export const schema = z.object({
firstName: z.string().min(1, "First name is required"),
lastName: z.string().min(1, "Last name is required"),
email: z.string().email("Invalid email address"),
phoneNumber: z.string().min(10, "Invalid phone number").max(10, "Invalid phone number"),
dateOfBirth: z.string().refine((val) => !isNaN(Date.parse(val)), {
message: "Invalid date format",
}),
video: z.instanceof(Blob, { message: "Video is required" }),
});
5 changes: 5 additions & 0 deletions ui/src/app/onboarding/components/FormSubmit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { FormData } from "./Types";

export const onSubmitAction = async (data: FormData) => {
console.log("Form submitted:", data);
};
4 changes: 4 additions & 0 deletions ui/src/app/onboarding/components/Types.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { z } from "zod";
import { schema } from "./FormSchema";

export type FormData = z.infer<typeof schema>;
141 changes: 141 additions & 0 deletions ui/src/app/onboarding/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
"use client";

import React, { useState } from "react";
import { Box, Row, Stack, Gradient, Text, Button, Socials, Icon, VideoCapture } from "../../components/ui";
import FormComponent from "./components/FormComponent";
import { SubmitHandler } from "react-hook-form";
import * as z from "zod";

const schema = z.object({
firstName: z.string().min(1, "First Name is required"),
lastName: z.string().min(1, "Last Name is required"),
email: z.string().email("Invalid email address"),
phoneNumber: z.string().min(10, "Phone Number must be at least 10 digits"),
dateOfBirth: z.string().refine((val: string) => !isNaN(Date.parse(val)), {
message: "Invalid date format",
}),
video: z.instanceof(Blob, { message: "Video is required" }),
});

type FormData = z.infer<typeof schema>;

const Onboarding: React.FC = () => {
const [isRecording, setIsRecording] = useState(false);
const [videoFile, setVideoFile] = useState<Blob | null>(null);
const [isSubmitted, setIsSubmitted] = useState(false);

const handleRecordingComplete = (recordedChunks: Blob[]) => {
const videoBlob = new Blob(recordedChunks, { type: "video/webm" });
setVideoFile(videoBlob);
console.log("Final video blob:", videoBlob);
};

const onSubmit: SubmitHandler<FormData> = (data) => {
console.log("onSubmit called with data:", data);

if (videoFile) {
console.log("Video file exists in onSubmit:", videoFile);
data.video = videoFile;

console.log("Form data with video:", data);

setIsSubmitted(true);
} else {
console.error("Video is required in onSubmit");
}
};

return (
<Box className="bg-primary-50">
<Stack>
<Gradient />
<Row className="w-full pt-14 px-20 items-center">
<Stack className="w-1/3 flex">
{isSubmitted ? (
<Text>User registered!</Text>
) : (
<FormComponent videoFile={videoFile} onSubmit={onSubmit} />
)}
</Stack>
<FaceScanSection
isRecording={isRecording}
setIsRecording={setIsRecording}
handleRecordingComplete={handleRecordingComplete}
/>
</Row>
<InfoSection />
</Stack>
</Box>
);
};

interface FaceScanSectionProps {
isRecording: boolean;
setIsRecording: React.Dispatch<React.SetStateAction<boolean>>;
handleRecordingComplete: (recordedChunks: Blob[]) => void;
}

const FaceScanSection: React.FC<FaceScanSectionProps> = ({ isRecording, setIsRecording, handleRecordingComplete }) => (
<Stack className="w-2/3 flex items-center place-content-center">
<Box className="w-96">
<VideoCapture
isRecording={isRecording}
onRecordingComplete={handleRecordingComplete}
/>
</Box>
<Box className="w-1/5 relative">
{isRecording ? (
<Row className="place-content-center pt-8">
<Button variant={"solid"} onClick={() => setIsRecording(false)}>
Stop Recording
</Button>
<Icon type="help" className="absolute -right-5 top-5" />
</Row>
) : (
<Row className="place-content-center pt-8">
<Button variant={"solid"} onClick={() => setIsRecording(true)}>
Start Recording
</Button>
<Icon type="help" className="absolute -right-5 top-5" />
</Row>
)}
</Box>
</Stack>
);

const InfoSection = () => (
<Stack className="p-14 items-center place-content-center">
<Box className="p-10 shadow-md rounded-md bg-white text-xl w-full ">
<Text as="a" weight="bold" className="shadow-inner bg-white" />
Hello, this is a registration form where you can register with a video of yourself! <br />
We will use this video to create biometrics, so you get access into the company and won't need to use a badge or card.
</Box>
<Row className="pt-14 space-x-10">
<Box className="w-1/2">
<Stack>
<Text size={"lg"} weight={"bold"} className="pb-5">
About UUFT.Ai
</Text>
<Text as="a">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatibus vero reiciendis quae porro, voluptates odit. Culpa ipsam beatae voluptas vitae est repudiandae, nulla atque, reiciendis labore, voluptatibus eum dolorem! Id inventore quidem ipsam impedit possimus?
</Text>
</Stack>
</Box>
<Box className="w-1/2">
<Stack>
<Text size={"lg"} weight={"bold"} className="pb-5">
About UUFT.Ai
</Text>
<Text as="a">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatibus vero reiciendis quae porro, voluptates odit. Culpa ipsam beatae voluptas vitae est repudiandae, nulla atque, reiciendis labore, voluptatibus eum dolorem! Id inventore quidem ipsam impedit possimus?
</Text>
</Stack>
</Box>
</Row>
<Box>
<Socials size={"lg"} className="pt-16" />
</Box>
</Stack>
);

export default Onboarding;
3 changes: 2 additions & 1 deletion ui/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
}
],
"paths": {
"@/*": ["./src/*"]
"@/*": ["./src/*"],
"@uug-ai/ui": ["./components/ui"]
},
"typeRoots": ["./src/types"]
},
Expand Down
Loading

0 comments on commit 1275f2a

Please sign in to comment.