Skip to content

Commit

Permalink
Merge pull request #237 from ShivanshPlays/multistep-form2
Browse files Browse the repository at this point in the history
Implement Individual Forms and Submission Logic for Guided Multistep Form in Vendor Dashboard
  • Loading branch information
Vimall03 authored Nov 7, 2024
2 parents 64dd4ea + 18447ff commit 657540f
Show file tree
Hide file tree
Showing 13 changed files with 728 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react';

// Define the type for the props
interface FormControlProps {
type: string;
id: string;
label: string;
placeholder: string;
value: string;
onchange: (e: React.ChangeEvent<HTMLInputElement>) => void;
valid: boolean;
}

const FormControl: React.FC<FormControlProps> = ({
type,
id,
label,
placeholder,
value,
onchange,
valid,
}) => {
return (
<div className="flex flex-col gap-1">
<div className="flex">
<div className="mr-auto">
<label className="text-primary-marineBlue font-medium" htmlFor={id}>
{label}
</label>
</div>
{valid ? null : (
<div>
<label className="text-red-500 font-medium" htmlFor={id}>
This field is required
</label>
</div>
)}
</div>
<input
id={id}
className={
valid
? 'w-full p-2 rounded-lg text-lg outline-none focus:border-primary-purplishBlue duration-700 border border-secondary-lightGray'
: 'w-full p-2 rounded-lg text-lg outline-none focus:border-primary-strawberryRed duration-700 border border-primary-strawberryRed'
}
type={type}
placeholder={placeholder}
value={value}
onChange={onchange}
/>
</div>
);
};

export default FormControl;
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const data = [
},
{
id: 3,
step: 'step 4',
step: 'step 3',
title: 'select tags',
},
];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import {
Select,
SelectTrigger,
SelectValue,
SelectContent,
SelectItem,
} from "@/components/ui/select";
import { useGlobalDish } from "@/context/dishFormContext";
import { Tag } from "@prisma/client";
import { useState } from "react";

const TagSelector = () => {
const tags = Object.values(Tag)
const {dishTags,setDishTags} = useGlobalDish()

const handleTagSelect = (tag:Tag) => {
if (!dishTags.includes(tag)) {
setDishTags([...dishTags, tag]);
}
};

const handleRemoveTag = (tag:Tag) => {
setDishTags(dishTags.filter((t) => t !== tag));
};

return (
<div>
<div className="mb-2">
<Select onValueChange={handleTagSelect}>
<SelectTrigger className="w-64">
<SelectValue placeholder="Select tags" />
</SelectTrigger>
<SelectContent>
{tags.map((tag) => (
<SelectItem key={tag} value={tag}>
{tag}
</SelectItem>
))}
</SelectContent>
</Select>
</div>

{/* Selected Tags */}
<div className="flex flex-wrap gap-2 mt-2">
{dishTags.map((tag) => (
<span
key={tag}
className="bg-blue-200 text-blue-800 px-3 py-1 rounded-full flex items-center space-x-2"
>
<span>{tag}</span>
<button
type="button"
onClick={() => handleRemoveTag(tag)}
className="text-sm text-blue-600"
>
×
</button>
</span>
))}
</div>
</div>
);
};

export default TagSelector;

81 changes: 81 additions & 0 deletions alimento-nextjs/components/multistepForm/pages/formPage1.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React from 'react';
import { useGlobalDish } from '@/context/dishFormContext';
import FormControl from '../components/formControl';

const FormPage1 = () => {
const {
dishName,
setDishName,
dishPrice,
setDishPrice,
dishDescription,
setDishDescription,

validDishName,
setValidDishName,
validDishPrice,
setValidDishPrice,
validDishDescription,
setValidDishDescription,
} = useGlobalDish();

const setDishNameLogic = (e: React.ChangeEvent<HTMLInputElement>) => {
setDishName(e.target.value);
setValidDishName(e.target.value.length >= 1);
};

const setDishDescriptionLogic = (
e: React.ChangeEvent<HTMLInputElement>
) => {
setDishDescription(e.target.value);
setValidDishDescription(e.target.value.length >= 1);
};

const setDishPriceLogic = (e: React.ChangeEvent<HTMLInputElement>) => {
setDishPrice(Number(e.target.value));
setValidDishPrice(e.target.value.length >= 1);
};

return (
<div className="flex flex-col gap-8">
<h1 className="text-primary-marineBlue font-bold text-[1.6rem] md:text-4xl leading-9">
Dish Info
</h1>
<h3 className="text-gray-400 mt-2">
Please provide your Dish name, description and price
</h3>

<div className="flex flex-col gap-5">
<FormControl
label={'Dish Title'}
type={'text'}
id={'dishName'}
placeholder={'pizza'}
onchange={setDishNameLogic}
value={dishName}
valid={validDishName}
/>
<FormControl
label={'Dish Description'}
type={'text'}
id={'dishDescription'}
placeholder={'large - 8 slices, margherita'}
onchange={setDishDescriptionLogic}
value={dishDescription}
valid={validDishDescription}
/>
<FormControl
label={'Dish Price'}
type={'number'}
id={'dishPrice'}
placeholder={'e.g. example@upi'}
onchange={setDishPriceLogic}
value={dishPrice.toString()}
valid={validDishPrice}
/>
</div>
</div>
);
};

export default FormPage1;
47 changes: 47 additions & 0 deletions alimento-nextjs/components/multistepForm/pages/formPage2.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { useGlobalDish } from '@/context/dishFormContext';
import { Category, Prisma } from '@prisma/client';
import { ChevronDown } from 'lucide-react';

const categories =Object.values(Category)

const FormPage2 = () => {
const { dishCategory,setDishCategory } = useGlobalDish();

return (
<div className="h-3/4 flex flex-col items-start gap-8 justify-start">
<h1 className="text-primary-marineBlue font-bold text-[1.6rem] md:text-4xl leading-9">
Select Category
</h1>
<h3 className="text-gray-400 mt-2">
Please select the most appropriate category for your dish
</h3>
<DropdownMenu>
<DropdownMenuTrigger className="bg-black h-10 text-gray-200 w-full rounded-full flex items-center justify-center">
{dishCategory || 'Category'} <ChevronDown />
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>
Select the Category for your dish
</DropdownMenuLabel>
<DropdownMenuSeparator />
{categories.map((category)=>(
<DropdownMenuItem key={category} onClick={() => setDishCategory(category)}>
{category}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
</div>
);
};

export default FormPage2;

19 changes: 19 additions & 0 deletions alimento-nextjs/components/multistepForm/pages/formPage3.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import TagSelector from '../components/tagSelector';

const FormPage3 = () => {

return (
<div className="h-3/4 flex flex-col items-start gap-8 justify-start">
<h1 className="text-primary-marineBlue font-bold text-[1.6rem] md:text-4xl leading-9">
Select Tags
</h1>
<h3 className="text-gray-400 mt-2">
Please select the most appropriate tags for your dish
</h3>
<TagSelector/>
</div>
);
};

export default FormPage3;

14 changes: 11 additions & 3 deletions alimento-nextjs/components/multistepForm/pages/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
import { useGlobalDish } from '@/context/dishFormContext';
import { MouseEventHandler, useEffect } from 'react';
import { Toaster } from 'react-hot-toast';
import FormPage1 from './formPage1';
import FormPage2 from './formPage2';
import TagSelector from './formPage3';

const Main = ({ sellerId }: { sellerId: string }) => {
const Main = ({ VendorId }: { VendorId: string }) => {
const {

dishName,
Expand All @@ -19,6 +22,8 @@ const Main = ({ sellerId }: { sellerId: string }) => {
formCompleted,
completed,
setCompleted,

submitListingForm
} = useGlobalDish();

// Use useEffect to update completed based on currentStep
Expand Down Expand Up @@ -70,7 +75,9 @@ const Main = ({ sellerId }: { sellerId: string }) => {
<div className="md:overflow-hidden md:min-h-full md:shadow-none shadow-md mx-auto md:m-0 rounded-xl md:rounded-none md:w-full w-[100%] md:bg-transparent min-h-[400px] bg-white z-10 mt-[84px]">
<form className="md:mx-16 md:my-0 mx-6 my-6 py-0 md:py-2 relative h-full">
<Toaster />
{currentStep === 1 && < div> The Forms will go Here </div>}
{currentStep === 1 && <FormPage1/>}
{currentStep === 2 && <FormPage2/>}
{currentStep === 3 && <TagSelector/>}
{!formCompleted && (
<footer className="md:block hidden w-full left-0 right-0 bottom-0">
<div className="flex">
Expand All @@ -90,7 +97,7 @@ const Main = ({ sellerId }: { sellerId: string }) => {
currentStep === 3
? e => {
e.preventDefault();

submitListingForm(VendorId)
}
: nextStep
}
Expand Down Expand Up @@ -124,6 +131,7 @@ const Main = ({ sellerId }: { sellerId: string }) => {
currentStep === 3
? e => {
e.preventDefault();
submitListingForm(VendorId)
}
: nextStep
}
Expand Down
2 changes: 1 addition & 1 deletion alimento-nextjs/components/multistepForm/pages/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const Sidebar = () => {

return (
<>
<aside className="bg-[url('/pngFood.png')] bg-cover bg-contain absolute top-0 left-0 right-0 md:relative md:bg-desktop h-[50vh] md:h-full p-8 overflow-hidden md:rounded-xl gap-4 md:gap-0 w-screen md:w-[42.5%] flex flex-row md:flex-col items-start md:justify-start justify-center">
<aside className="bg-[url('/pngFood.png')] bg-contain absolute top-0 left-0 right-0 md:relative md:bg-desktop h-[50vh] md:h-full p-8 overflow-hidden md:rounded-xl gap-4 md:gap-0 w-screen md:w-[42.5%] flex flex-row md:flex-col items-start md:justify-start justify-center">
{data.map((data, index) => {
const { id, step, title } = data;

Expand Down
3 changes: 2 additions & 1 deletion alimento-nextjs/components/multistepForm/setupDishes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import React from "react";
import Image from "next/image";
import Sidebar from "./pages/sidebar";
import Main from "./pages/main";

const SetUpDishes = ({ VendorId }: { VendorId: string }) => {
return (
Expand All @@ -20,7 +21,7 @@ const SetUpDishes = ({ VendorId }: { VendorId: string }) => {

<div className="md:gray-200 bg-gray-200 dark:bg-gray-700 rounded-xl shadow-md absolute md:relative p-4 flex md:flex-row flex-col md:max-h-[550px] md:max-w-[900px] h-full w-full">
<Sidebar />
{/* <Main VendorId={VendorId} /> */}
<Main VendorId={VendorId} />
</div>
</main>
</>
Expand Down
Loading

0 comments on commit 657540f

Please sign in to comment.