Refactor Apply page component to use DualOptionSelector component for handling yes/no choices

This commit is contained in:
Pattadon 2024-10-11 11:43:06 +07:00
parent 55b8d8759b
commit a3573c5c9a
3 changed files with 116 additions and 55 deletions

View File

@ -24,16 +24,23 @@ import {
} from "@/components/ui/tooltip"; } from "@/components/ui/tooltip";
import { z } from "zod"; import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { Selector } from "@/components/selector"; import { DualOptionSelector } from "@/components/dualSelector";
import { MultipleOptionSelector } from "@/components/multipleSelector";
export default function Apply() { export default function Apply() {
const formSchema = z.object({ const formSchema = z.object({
companyName: z.string().min(5, { companyName: z.string().min(5, {
message: "Company name must be at least 5 characters.", message: "Company name must be at least 5 characters.",
}), }),
totalRaised: z.number().int({ industry: z.string(),
message: "Total raised must be an integer.", isInUS: z.string(),
}), totalRaised: z
.number({
required_error: "Total raised must be a number.",
invalid_type_error: "Total raised must be a valid number.",
})
.positive()
.max(9999999999, "Total raised must be a realistic amount."),
}); });
let supabase = createSupabaseClient(); let supabase = createSupabaseClient();
const { const {
@ -45,7 +52,6 @@ export default function Apply() {
resolver: zodResolver(formSchema), resolver: zodResolver(formSchema),
}); });
const [industry, setIndustry] = useState<string[]>([]); const [industry, setIndustry] = useState<string[]>([]);
const [selectedIndustry, setSelectedIndustry] = useState("");
const [isInUS, setIsInUS] = useState(""); const [isInUS, setIsInUS] = useState("");
const [isForSale, setIsForSale] = useState(""); const [isForSale, setIsForSale] = useState("");
const [isGenerating, setIsGenerating] = useState(""); const [isGenerating, setIsGenerating] = useState("");
@ -65,6 +71,13 @@ export default function Apply() {
"100K+", "100K+",
]; ];
useEffect(() => {
register("industry");
register("isInUS");
register("isForSale");
register("isGenerating");
}, [register]);
const handleRemoveImage = (index: number) => { const handleRemoveImage = (index: number) => {
const updatedImages = selectedImages.filter((_, i) => i !== index); const updatedImages = selectedImages.filter((_, i) => i !== index);
setSelectedImages(updatedImages); setSelectedImages(updatedImages);
@ -79,11 +92,8 @@ export default function Apply() {
const onSubmit = (data: any) => { const onSubmit = (data: any) => {
console.table(data); console.table(data);
}; };
const handleFieldChange = (fieldName: string, value: string) => { const handleFieldChange = (fieldName: string, value: any) => {
switch (fieldName) { switch (fieldName) {
case "industry":
setSelectedIndustry(value);
break;
case "isInUS": case "isInUS":
setIsInUS(value); setIsInUS(value);
break; break;
@ -147,7 +157,7 @@ export default function Apply() {
</div> </div>
{/* form */} {/* form */}
<form action="" onSubmit={handleSubmit(onSubmit)}> <form action="" onSubmit={handleSubmit(onSubmit)}>
<div className="grid grid-flow-row auto-rows-max w-3/4 ml-48"> <div className="grid grid-flow-row auto-rows-max w-3/4 ml-1/2">
<h1 className="text-3xl font-bold mt-10 ml-96">About your company</h1> <h1 className="text-3xl font-bold mt-10 ml-96">About your company</h1>
<p className="ml-96 mt-5 text-neutral-500"> <p className="ml-96 mt-5 text-neutral-500">
All requested information in this section is required. All requested information in this section is required.
@ -182,41 +192,24 @@ export default function Apply() {
)} )}
</div> </div>
{/* industry */} {/* industry */}
<div className="mt-10 space-y-5">
<Label htmlFor="industry" className="font-bold text-lg mt-10"> <MultipleOptionSelector
Industry header={<>Industry</>}
</Label> fieldName="industry"
<div className="flex space-x-5"> choices={industry}
<Select handleFunction={handleFieldChange}
onValueChange={(value) => description={
handleFieldChange("industry", value) <>Choose the industry that best aligns with your business.</>
} }
> placeholder="Select an industry"
<SelectTrigger className="w-96"> selectLabel="Industry"
<SelectValue placeholder="Select an industry" /> />
</SelectTrigger> {/* <input
<SelectContent>
<SelectGroup>
<SelectLabel>Industry</SelectLabel>
{industry.map((i) => (
<SelectItem key={i} value={i}>
{i}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
<input
type="hidden" type="hidden"
{...register("industry")} {...register("industry")}
value={selectedIndustry} value={selectedIndustry}
/> /> */}
{/* {selectedIndustry} */} {/* {selectedIndustry} */}
<span className="text-[12px] text-neutral-500 self-center">
Choose the industry that best aligns with your business.
</span>
</div>
</div>
{/* How much money has your company raised to date? */} {/* How much money has your company raised to date? */}
<div className="space-y-5"> <div className="space-y-5">
<Label htmlFor="totalRaised" className="font-bold text-lg"> <Label htmlFor="totalRaised" className="font-bold text-lg">
@ -224,11 +217,13 @@ export default function Apply() {
</Label> </Label>
<div className="flex space-x-5"> <div className="flex space-x-5">
<Input <Input
type="text" type="number"
id="totalRaised" id="totalRaised"
className="w-96" className="w-96"
placeholder="$ 1,000,000" placeholder="$ 1,000,000"
{...register("totalRaised")} {...register("totalRaised", {
valueAsNumber: true,
})}
/> />
<span className="text-[12px] text-neutral-500 self-center"> <span className="text-[12px] text-neutral-500 self-center">
The sum total of past financing, including angel or venture{" "} The sum total of past financing, including angel or venture{" "}
@ -236,9 +231,18 @@ export default function Apply() {
capital, loans, grants, or token sales. capital, loans, grants, or token sales.
</span> </span>
</div> </div>
{errors.totalRaised && (
<p className="text-red-500 text-sm">
{errors.totalRaised && (
<p className="text-red-500 text-sm">
{errors.totalRaised.message as string}
</p>
)}
</p>
)}
</div> </div>
{/* Is your company incorporated in the United States? */} {/* Is your company incorporated in the United States? */}
<Selector <DualOptionSelector
label={ label={
<> <>
Is your company incorporated in the <br /> Is your company incorporated in the <br />
@ -262,7 +266,7 @@ export default function Apply() {
/> />
{/* Is your product available (for sale) in market? */} {/* Is your product available (for sale) in market? */}
<Selector <DualOptionSelector
label={ label={
<> <>
Is your product available (for sale) <br /> Is your product available (for sale) <br />
@ -284,7 +288,7 @@ export default function Apply() {
/> />
{/* Is your company generating revenue?*/} {/* Is your company generating revenue?*/}
<Selector <DualOptionSelector
label={<>Is your company generating revenue?</>} label={<>Is your company generating revenue?</>}
name="isGenerating" name="isGenerating"
choice1="Yes" choice1="Yes"
@ -367,10 +371,11 @@ export default function Apply() {
</span> </span>
</div> </div>
</div> </div>
<div className="flex space-x-5"> <div className="flex space-x-5">
<Switch onCheckedChange={() => setApplyProject(!applyProject)}> <Switch
Apply your first project! onCheckedChange={() => setApplyProject(!applyProject)}
</Switch> ></Switch>
<TooltipProvider> <TooltipProvider>
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
@ -396,7 +401,7 @@ export default function Apply() {
{applyProject && ( {applyProject && (
<div className="grid auto-rows-max w-3/4 ml-48 bg-zinc-100 dark:bg-zinc-900 mt-10 pt-12 pb-12"> <div className="grid auto-rows-max w-3/4 ml-48 bg-zinc-100 dark:bg-zinc-900 mt-10 pt-12 pb-12">
{/* header */} {/* header */}
<div className="ml-96"> <div className="ml-[15%]">
<h1 className="text-3xl font-bold mt-10"> <h1 className="text-3xl font-bold mt-10">
Begin Your First Fundraising Project Begin Your First Fundraising Project
</h1> </h1>

View File

@ -12,7 +12,7 @@ interface SelectorInterface {
description: ReactElement; description: ReactElement;
} }
export function Selector(props: SelectorInterface) { export function DualOptionSelector(props: SelectorInterface) {
return ( return (
<div className="space-y-5"> <div className="space-y-5">
<Label htmlFor={props.name} className="font-bold text-lg"> <Label htmlFor={props.name} className="font-bold text-lg">

View File

@ -0,0 +1,56 @@
import { Label } from "@/components/ui/label";
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { ReactElement } from "react";
interface MultipleOptionSelector {
header: ReactElement;
fieldName: string;
choices: string[];
handleFunction: Function;
description: ReactElement;
placeholder: string;
selectLabel: string;
}
export function MultipleOptionSelector(props: MultipleOptionSelector) {
return (
<div className="mt-10 space-y-5">
<Label htmlFor={props.fieldName} className="font-bold text-lg mt-10">
{props.header}
</Label>
<div className="flex space-x-5">
<Select
onValueChange={(value) => {
props.handleFunction(props.fieldName, value);
// console.log(value, props.fieldName);
}}
>
<SelectTrigger className="w-96">
<SelectValue placeholder={props.placeholder} />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>{props.selectLabel}</SelectLabel>
{props.choices.map((i) => (
<SelectItem key={i} value={i}>
{i}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
<span className="text-[12px] text-neutral-500 self-center">
{props.description}
</span>
</div>
</div>
);
}