Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Food Cart #18

Merged
merged 8 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import Foods from '@pages/BranchManager/Foods';
import FoodItem from '@pages/FoodItem';
import AllFoodItems from '@pages/AllFoodItems';
import { Gallery } from '@components/Gallery/Gallery';
import Cart from '@pages/Cart';
import { OrderHistory } from './components/User/OrderHistory/OrderHistory';

const routes = createRoutesFromElements(
Expand All @@ -40,6 +41,15 @@ const routes = createRoutesFromElements(
</>
}
/>
<Route
path="cart"
element={
<>
<PageTitle title="La Fresca | Cart" />
<Cart />
</>
}
/>
<Route
path="orderhistory"
element={
Expand Down
204 changes: 142 additions & 62 deletions src/components/BranchManager/Forms/DynamicForm/index.tsx

Large diffs are not rendered by default.

245 changes: 40 additions & 205 deletions src/components/BranchManager/Forms/MultiSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,217 +1,52 @@
import React, { useState, useEffect, useRef } from 'react';

interface Option {
value: string;
text: string;
selected: boolean;
element?: HTMLElement;
}

interface DropdownProps {
id: string;
import { FC } from 'react';
import { Select, SelectItem } from '@nextui-org/react';
import { Category } from '@/types/category';
import { UseFormRegister } from 'react-hook-form';

interface AppProps {
categories: Category[];
fieldname: string;
register: UseFormRegister<any>; // Assuming your form data type can be any
}

const MultiSelect: React.FC<DropdownProps> = ({ id }) => {
const [options, setOptions] = useState<Option[]>([]);
const [selected, setSelected] = useState<number[]>([]);
const [show, setShow] = useState(false);
const dropdownRef = useRef<any>(null);
const trigger = useRef<any>(null);

useEffect(() => {
const loadOptions = () => {
const select = document.getElementById(id) as HTMLSelectElement | null;
if (select) {
const newOptions: Option[] = [];
for (let i = 0; i < select.options.length; i++) {
newOptions.push({
value: select.options[i].value,
text: select.options[i].innerText,
selected: select.options[i].hasAttribute('selected'),
});
}
setOptions(newOptions);
}
};

loadOptions();
}, [id]);

const open = () => {
setShow(true);
};

const isOpen = () => {
return show === true;
};

const select = (index: number, event: React.MouseEvent) => {
const newOptions = [...options];

if (!newOptions[index].selected) {
newOptions[index].selected = true;
newOptions[index].element = event.currentTarget as HTMLElement;
setSelected([...selected, index]);
} else {
const selectedIndex = selected.indexOf(index);
if (selectedIndex !== -1) {
newOptions[index].selected = false;
setSelected(selected.filter((i) => i !== index));
}
}

setOptions(newOptions);
};

const remove = (index: number) => {
const newOptions = [...options];
const selectedIndex = selected.indexOf(index);

if (selectedIndex !== -1) {
newOptions[index].selected = false;
setSelected(selected.filter((i) => i !== index));
setOptions(newOptions);
}
};

const selectedValues = () => {
return selected.map((option) => options[option].value);
};

useEffect(() => {
const clickHandler = ({ target }: MouseEvent) => {
if (!dropdownRef.current) return;
if (
!show ||
dropdownRef.current.contains(target) ||
trigger.current.contains(target)
)
return;
setShow(false);
};
document.addEventListener('click', clickHandler);
return () => document.removeEventListener('click', clickHandler);
});

const App: FC<AppProps> = ({ categories, register, fieldname }) => {
return (
<div className="relative z-50">
<label className="mb-3 block text-sm font-medium text-black dark:text-white">
Multiselect Dropdown
</label>
<div className="relative">
<div>
<select className="hidden" id={id}>
<option value="1">Option 2</option>
<option value="2">Option 3</option>
<option value="3">Option 4</option>
<option value="4">Option 5</option>
</select>

<div className="flex flex-col items-center">
<input name="values" type="hidden" defaultValue={selectedValues()} />
{/* Use register to bind select input to react-hook-form */}
<select
{...register('category')}
className="hidden"
id="category-select"
>
{categories.map((category) => (
<option key={category.key} value={category.key}>
{category.label}
</option>
))}
</select>
<div className="relative z-20 inline-block w-full">
<div className="relative flex flex-col items-center">
<div ref={trigger} onClick={open} className="w-full">
<div className="mb-2 flex rounded border border-stroke py-2 pl-3 pr-3 outline-none transition focus:border-primary active:border-primary dark:border-form-strokedark dark:bg-form-input">
<div className="w-full">
<div className="mb-2 flex rounded border border-stroke py-2 pl-3 pr-3 outline-none transition focus:border-primary active:border-primary dark:border-form-strokedark bg-inherit">
<div className="flex flex-auto flex-wrap gap-3">
{selected.map((index) => (
<div
key={index}
className="my-1.5 flex items-center justify-center rounded border-[.5px] border-stroke bg-gray px-2.5 py-1.5 text-sm font-medium dark:border-strokedark dark:bg-white/30"
>
<div className="max-w-full flex-initial">
{options[index].text}
</div>
<div className="flex flex-auto flex-row-reverse">
<div
onClick={() => remove(index)}
className="cursor-pointer pl-2 hover:text-danger"
>
<svg
className="fill-current"
role="button"
width="12"
height="12"
viewBox="0 0 12 12"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M9.35355 3.35355C9.54882 3.15829 9.54882 2.84171 9.35355 2.64645C9.15829 2.45118 8.84171 2.45118 8.64645 2.64645L6 5.29289L3.35355 2.64645C3.15829 2.45118 2.84171 2.45118 2.64645 2.64645C2.45118 2.84171 2.45118 3.15829 2.64645 3.35355L5.29289 6L2.64645 8.64645C2.45118 8.84171 2.45118 9.15829 2.64645 9.35355C2.84171 9.54882 3.15829 9.54882 3.35355 9.35355L6 6.70711L8.64645 9.35355C8.84171 9.54882 9.15829 9.54882 9.35355 9.35355C9.54882 9.15829 9.54882 8.84171 9.35355 8.64645L6.70711 6L9.35355 3.35355Z"
fill="currentColor"
></path>
</svg>
</div>
</div>
</div>
))}
{selected.length === 0 && (
<div className="flex-1">
<input
placeholder="Select an option"
className="h-full w-full appearance-none bg-transparent p-1 px-2 outline-none"
defaultValue={selectedValues()}
/>
</div>
)}
</div>
<div className="flex w-8 items-center py-1 pl-1 pr-1">
<button
type="button"
onClick={open}
className="h-6 w-6 cursor-pointer outline-none focus:outline-none"
{/* Use Select from @nextui-org/react */}
<Select
items={categories}
placeholder="Select an option"
className="w-full"
{...register(fieldname)} // Ensure register is applied to Select
>
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g opacity="0.8">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.29289 8.29289C5.68342 7.90237 6.31658 7.90237 6.70711 8.29289L12 13.5858L17.2929 8.29289C17.6834 7.90237 18.3166 7.90237 18.7071 8.29289C19.0976 8.68342 19.0976 9.31658 18.7071 9.70711L12.7071 15.7071C12.3166 16.0976 11.6834 16.0976 11.2929 15.7071L5.29289 9.70711C4.90237 9.31658 4.90237 8.68342 5.29289 8.29289Z"
fill="#637381"
></path>
</g>
</svg>
</button>
</div>
</div>
</div>
<div className="w-full px-4">
<div
className={`max-h-select absolute top-full left-0 z-40 w-full overflow-y-auto rounded bg-white shadow dark:bg-form-input ${
isOpen() ? '' : 'hidden'
}`}
ref={dropdownRef}
onFocus={() => setShow(true)}
onBlur={() => setShow(false)}
>
<div className="flex w-full flex-col">
{options.map((option, index) => (
<div key={index}>
<div
className="w-full cursor-pointer rounded-t border-b border-stroke hover:bg-primary/5 dark:border-form-strokedark"
onClick={(event) => select(index, event)}
{(category) => (
<SelectItem
className="dark:bg-[#000000] rounded-sm border border-solid w-full"
key={category.key}
>
<div
className={`relative flex w-full items-center border-l-2 border-transparent p-2 pl-2 ${
option.selected ? 'border-primary' : ''
}`}
>
<div className="flex w-full items-center">
<div className="mx-2 leading-6">
{option.text}
</div>
</div>
</div>
</div>
</div>
))}
{category.label}
</SelectItem>
)}
</Select>
</div>
</div>
</div>
Expand All @@ -223,4 +58,4 @@ const MultiSelect: React.FC<DropdownProps> = ({ id }) => {
);
};

export default MultiSelect;
export default App;
Loading
Loading