Init(Core): add to repo and add seeders

This commit is contained in:
2026-04-28 22:48:42 +03:30
commit be6b699ff0
205 changed files with 22524 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
import { useEffect } from 'react';
import GuestLayout from '@/Layouts/GuestLayout';
import InputError from '@/Components/InputError';
import InputLabel from '@/Components/InputLabel';
import PrimaryButton from '@/Components/PrimaryButton';
import TextInput from '@/Components/TextInput';
import { Head, useForm } from '@inertiajs/react';
export default function ConfirmPassword() {
const { data, setData, post, processing, errors, reset } = useForm({
password: '',
});
useEffect(() => {
return () => {
reset('password');
};
}, []);
const submit = (e) => {
e.preventDefault();
post(route('password.confirm'));
};
return (
<GuestLayout>
<Head title="Confirm Password" />
<div className="mb-4 text-sm text-gray-600">
This is a secure area of the application. Please confirm your password before continuing.
</div>
<form onSubmit={submit}>
<div className="mt-4">
<InputLabel htmlFor="password" value="Password" />
<TextInput
id="password"
type="password"
name="password"
value={data.password}
className="mt-1 block w-full"
isFocused={true}
onChange={(e) => setData('password', e.target.value)}
/>
<InputError message={errors.password} className="mt-2" />
</div>
<div className="flex items-center justify-end mt-4">
<PrimaryButton className="ml-4" disabled={processing}>
Confirm
</PrimaryButton>
</div>
</form>
</GuestLayout>
);
}

View File

@@ -0,0 +1,50 @@
import GuestLayout from '@/Layouts/GuestLayout';
import InputError from '@/Components/InputError';
import PrimaryButton from '@/Components/PrimaryButton';
import TextInput from '@/Components/TextInput';
import { Head, useForm } from '@inertiajs/react';
export default function ForgotPassword({ status }) {
const { data, setData, post, processing, errors } = useForm({
email: '',
});
const submit = (e) => {
e.preventDefault();
post(route('password.email'));
};
return (
<GuestLayout>
<Head title="Forgot Password" />
<div className="mb-4 text-sm text-gray-600">
Forgot your password? No problem. Just let us know your email address and we will email you a password
reset link that will allow you to choose a new one.
</div>
{status && <div className="mb-4 font-medium text-sm text-green-600">{status}</div>}
<form onSubmit={submit}>
<TextInput
id="email"
type="email"
name="email"
value={data.email}
className="mt-1 block w-full"
isFocused={true}
onChange={(e) => setData('email', e.target.value)}
/>
<InputError message={errors.email} className="mt-2" />
<div className="flex items-center justify-end mt-4">
<PrimaryButton className="ml-4" disabled={processing}>
Email Password Reset Link
</PrimaryButton>
</div>
</form>
</GuestLayout>
);
}

View File

@@ -0,0 +1,97 @@
import { useEffect } from 'react';
import Checkbox from '@/Components/Checkbox';
import GuestLayout from '@/Layouts/GuestLayout';
import InputError from '@/Components/InputError';
import InputLabel from '@/Components/InputLabel';
import PrimaryButton from '@/Components/PrimaryButton';
import TextInput from '@/Components/TextInput';
import { Head, Link, useForm } from '@inertiajs/react';
export default function Login({ status, canResetPassword }) {
const { data, setData, post, processing, errors, reset } = useForm({
email: '',
password: '',
remember: false,
});
useEffect(() => {
return () => {
reset('password');
};
}, []);
const submit = (e) => {
e.preventDefault();
post(route('login'));
};
return (
<GuestLayout>
<Head title="Log in" />
{status && <div className="mb-4 font-medium text-sm text-green-600">{status}</div>}
<form onSubmit={submit}>
<div>
<InputLabel htmlFor="email" value="Email" />
<TextInput
id="email"
type="email"
name="email"
value={data.email}
className="mt-1 block w-full"
autoComplete="username"
isFocused={true}
onChange={(e) => setData('email', e.target.value)}
/>
<InputError message={errors.email} className="mt-2" />
</div>
<div className="mt-4">
<InputLabel htmlFor="password" value="Password" />
<TextInput
id="password"
type="password"
name="password"
value={data.password}
className="mt-1 block w-full"
autoComplete="current-password"
onChange={(e) => setData('password', e.target.value)}
/>
<InputError message={errors.password} className="mt-2" />
</div>
<div className="block mt-4">
<label className="flex items-center">
<Checkbox
name="remember"
checked={data.remember}
onChange={(e) => setData('remember', e.target.checked)}
/>
<span className="ml-2 text-sm text-gray-600">Remember me</span>
</label>
</div>
<div className="flex items-center justify-end mt-4">
{canResetPassword && (
<Link
href={route('password.request')}
className="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Forgot your password?
</Link>
)}
<PrimaryButton className="ml-4" disabled={processing}>
Log in
</PrimaryButton>
</div>
</form>
</GuestLayout>
);
}

View File

@@ -0,0 +1,117 @@
import { useEffect } from 'react';
import GuestLayout from '@/Layouts/GuestLayout';
import InputError from '@/Components/InputError';
import InputLabel from '@/Components/InputLabel';
import PrimaryButton from '@/Components/PrimaryButton';
import TextInput from '@/Components/TextInput';
import { Head, Link, useForm } from '@inertiajs/react';
export default function Register() {
const { data, setData, post, processing, errors, reset } = useForm({
name: '',
email: '',
password: '',
password_confirmation: '',
});
useEffect(() => {
return () => {
reset('password', 'password_confirmation');
};
}, []);
const submit = (e) => {
e.preventDefault();
post(route('register'));
};
return (
<GuestLayout>
<Head title="Register" />
<form onSubmit={submit}>
<div>
<InputLabel htmlFor="name" value="Name" />
<TextInput
id="name"
name="name"
value={data.name}
className="mt-1 block w-full"
autoComplete="name"
isFocused={true}
onChange={(e) => setData('name', e.target.value)}
required
/>
<InputError message={errors.name} className="mt-2" />
</div>
<div className="mt-4">
<InputLabel htmlFor="email" value="Email" />
<TextInput
id="email"
type="email"
name="email"
value={data.email}
className="mt-1 block w-full"
autoComplete="username"
onChange={(e) => setData('email', e.target.value)}
required
/>
<InputError message={errors.email} className="mt-2" />
</div>
<div className="mt-4">
<InputLabel htmlFor="password" value="Password" />
<TextInput
id="password"
type="password"
name="password"
value={data.password}
className="mt-1 block w-full"
autoComplete="new-password"
onChange={(e) => setData('password', e.target.value)}
required
/>
<InputError message={errors.password} className="mt-2" />
</div>
<div className="mt-4">
<InputLabel htmlFor="password_confirmation" value="Confirm Password" />
<TextInput
id="password_confirmation"
type="password"
name="password_confirmation"
value={data.password_confirmation}
className="mt-1 block w-full"
autoComplete="new-password"
onChange={(e) => setData('password_confirmation', e.target.value)}
required
/>
<InputError message={errors.password_confirmation} className="mt-2" />
</div>
<div className="flex items-center justify-end mt-4">
<Link
href={route('login')}
className="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Already registered?
</Link>
<PrimaryButton className="ml-4" disabled={processing}>
Register
</PrimaryButton>
</div>
</form>
</GuestLayout>
);
}

View File

@@ -0,0 +1,90 @@
import { useEffect } from 'react';
import GuestLayout from '@/Layouts/GuestLayout';
import InputError from '@/Components/InputError';
import InputLabel from '@/Components/InputLabel';
import PrimaryButton from '@/Components/PrimaryButton';
import TextInput from '@/Components/TextInput';
import { Head, useForm } from '@inertiajs/react';
export default function ResetPassword({ token, email }) {
const { data, setData, post, processing, errors, reset } = useForm({
token: token,
email: email,
password: '',
password_confirmation: '',
});
useEffect(() => {
return () => {
reset('password', 'password_confirmation');
};
}, []);
const submit = (e) => {
e.preventDefault();
post(route('password.store'));
};
return (
<GuestLayout>
<Head title="Reset Password" />
<form onSubmit={submit}>
<div>
<InputLabel htmlFor="email" value="Email" />
<TextInput
id="email"
type="email"
name="email"
value={data.email}
className="mt-1 block w-full"
autoComplete="username"
onChange={(e) => setData('email', e.target.value)}
/>
<InputError message={errors.email} className="mt-2" />
</div>
<div className="mt-4">
<InputLabel htmlFor="password" value="Password" />
<TextInput
id="password"
type="password"
name="password"
value={data.password}
className="mt-1 block w-full"
autoComplete="new-password"
isFocused={true}
onChange={(e) => setData('password', e.target.value)}
/>
<InputError message={errors.password} className="mt-2" />
</div>
<div className="mt-4">
<InputLabel htmlFor="password_confirmation" value="Confirm Password" />
<TextInput
type="password"
name="password_confirmation"
value={data.password_confirmation}
className="mt-1 block w-full"
autoComplete="new-password"
onChange={(e) => setData('password_confirmation', e.target.value)}
/>
<InputError message={errors.password_confirmation} className="mt-2" />
</div>
<div className="flex items-center justify-end mt-4">
<PrimaryButton className="ml-4" disabled={processing}>
Reset Password
</PrimaryButton>
</div>
</form>
</GuestLayout>
);
}

View File

@@ -0,0 +1,45 @@
import GuestLayout from '@/Layouts/GuestLayout';
import PrimaryButton from '@/Components/PrimaryButton';
import { Head, Link, useForm } from '@inertiajs/react';
export default function VerifyEmail({ status }) {
const { post, processing } = useForm({});
const submit = (e) => {
e.preventDefault();
post(route('verification.send'));
};
return (
<GuestLayout>
<Head title="Email Verification" />
<div className="mb-4 text-sm text-gray-600">
Thanks for signing up! Before getting started, could you verify your email address by clicking on the
link we just emailed to you? If you didn't receive the email, we will gladly send you another.
</div>
{status === 'verification-link-sent' && (
<div className="mb-4 font-medium text-sm text-green-600">
A new verification link has been sent to the email address you provided during registration.
</div>
)}
<form onSubmit={submit}>
<div className="mt-4 flex items-center justify-between">
<PrimaryButton disabled={processing}>Resend Verification Email</PrimaryButton>
<Link
href={route('logout')}
method="post"
as="button"
className="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Log Out
</Link>
</div>
</form>
</GuestLayout>
);
}

View File

@@ -0,0 +1,46 @@
import Layout from '@/Layouts/Layout';
import Searchbar from '@/Components/Searchbar';
import CreateButton from '@/Components/CreateButton';
import CategoryForm from '@/Components/CategoryForm';
import CategoryCard from '@/Components/CategoryCard';
import { useState } from 'react'
import { router } from '@inertiajs/react'
export default function Index({ categories }){
let [createOpen, setCreateOpen] = useState(false);
function handleCancel(){
setCreateOpen(false);
}
function handleCreateClick(){
setCreateOpen(true);
}
function handleCreate(){
setCreateOpen(false);
router.refresh();
}
const category_list = categories.map((category) => (
<CategoryCard category={ category } />
));
return (
<div className="relative flex flex-col h-full w-full space-y-6">
{createOpen ? <div className="flex items-center justify-center absolute top-0 z-50 backdrop-blur h-full w-full rounded-lg backdrop-brightness-75">
<CategoryForm onCancel = {handleCancel}/>
</div> : ''}
<div className="flex justify-between h-fit">
<Searchbar />
<CreateButton onClick={ handleCreateClick } title="افزودن دسته بندی"/>
</div>
<div className="grid grid-cols-2 gap-8 ">
{category_list}
</div>
</div>
);
}
Index.layout = page => <Layout children={page} />

View File

@@ -0,0 +1,19 @@
import Layout from '@/Layouts/Layout';
import Searchbar from '@/Components/Searchbar';
import CreateButton from '@/Components/CreateButton';
import ProductForm from '@/Components/ProductForm';
import ProductTable from '@/Components/ProductTable';
import { useState } from 'react'
import { router } from '@inertiajs/react'
export default function Index({ contents }){
return (
<div className="relative flex flex-col h-full w-full space-y-6">
hello
</div>
);
}
Index.layout = page => <Layout children={page} />

View File

@@ -0,0 +1,13 @@
import Layout from '@/Layouts/Layout';
export default function Dashboard({ data, visits }) {
return (
<div className="grid grid-cols-12 grid-rows-12 gap-6 h-full w-full">
Hello
</div>
);
}
Dashboard.layout = page => <Layout children={page} />

View File

@@ -0,0 +1,53 @@
import Layout from '@/Layouts/Layout';
import Searchbar from '@/Components/Searchbar';
import CreateButton from '@/Components/CreateButton';
import ProductForm from '@/Components/ProductForm';
import ProductTable from '@/Components/ProductTable';
import { useState } from 'react'
import { router } from '@inertiajs/react'
export default function Index({ products, links, categories }){
let [createOpen, setCreateOpen] = useState(false);
function handleCancel(){
setCreateOpen(false);
}
function handleCreateClick(){
setCreateOpen(true);
}
function handleCreate(){
setCreateOpen(false);
router.refresh();
}
const product_list = products.map((product) => (
<div className="flex flex-col items-center justify-center bg-white rounded-lg w-full h-full">
{product.images[0] ? <img src={ product.images[0].thumbnail } alt={ product.images[0].alt } className="h-52 w-full object-cover rounded-t-lg shadow-md" /> : null}
<div className="p-4 py-6 flex flex-col items-center justify-center space-y-4">
<span className="text-xl">{product.title}</span>
<span className="text-gray-600 text-center">{product.description}</span>
</div>
</div>
));
return (
<div className="relative flex flex-col h-full w-full space-y-6">
{createOpen ? <div className="flex items-center justify-center absolute top-0 z-10 backdrop-blur h-full w-full rounded-lg backdrop-brightness-75">
<ProductForm onCancel = {handleCancel} categories={ categories }/>
</div> : ''}
<div className="flex justify-between h-fit">
<Searchbar />
<CreateButton onClick={ handleCreateClick } title="افزودن محصول"/>
</div>
<div className="grid grid-cols-4 gap-8">
{product_list}
</div>
<ProductTable items={ products } links={ links } title="محصولات" />
</div>
);
}
Index.layout = page => <Layout children={page} />

View File

@@ -0,0 +1,36 @@
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
import DeleteUserForm from './Partials/DeleteUserForm';
import UpdatePasswordForm from './Partials/UpdatePasswordForm';
import UpdateProfileInformationForm from './Partials/UpdateProfileInformationForm';
import { Head } from '@inertiajs/react';
export default function Edit({ auth, mustVerifyEmail, status }) {
return (
<AuthenticatedLayout
user={auth.user}
header={<h2 className="font-semibold text-xl text-gray-800 leading-tight">Profile</h2>}
>
<Head title="Profile" />
<div className="py-12">
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
<div className="p-4 sm:p-8 bg-white shadow sm:rounded-lg">
<UpdateProfileInformationForm
mustVerifyEmail={mustVerifyEmail}
status={status}
className="max-w-xl"
/>
</div>
<div className="p-4 sm:p-8 bg-white shadow sm:rounded-lg">
<UpdatePasswordForm className="max-w-xl" />
</div>
<div className="p-4 sm:p-8 bg-white shadow sm:rounded-lg">
<DeleteUserForm className="max-w-xl" />
</div>
</div>
</div>
</AuthenticatedLayout>
);
}

View File

@@ -0,0 +1,99 @@
import { useRef, useState } from 'react';
import DangerButton from '@/Components/DangerButton';
import InputError from '@/Components/InputError';
import InputLabel from '@/Components/InputLabel';
import Modal from '@/Components/Modal';
import SecondaryButton from '@/Components/SecondaryButton';
import TextInput from '@/Components/TextInput';
import { useForm } from '@inertiajs/react';
export default function DeleteUserForm({ className = '' }) {
const [confirmingUserDeletion, setConfirmingUserDeletion] = useState(false);
const passwordInput = useRef();
const {
data,
setData,
delete: destroy,
processing,
reset,
errors,
} = useForm({
password: '',
});
const confirmUserDeletion = () => {
setConfirmingUserDeletion(true);
};
const deleteUser = (e) => {
e.preventDefault();
destroy(route('profile.destroy'), {
preserveScroll: true,
onSuccess: () => closeModal(),
onError: () => passwordInput.current.focus(),
onFinish: () => reset(),
});
};
const closeModal = () => {
setConfirmingUserDeletion(false);
reset();
};
return (
<section className={`space-y-6 ${className}`}>
<header>
<h2 className="text-lg font-medium text-gray-900">Delete Account</h2>
<p className="mt-1 text-sm text-gray-600">
Once your account is deleted, all of its resources and data will be permanently deleted. Before
deleting your account, please download any data or information that you wish to retain.
</p>
</header>
<DangerButton onClick={confirmUserDeletion}>Delete Account</DangerButton>
<Modal show={confirmingUserDeletion} onClose={closeModal}>
<form onSubmit={deleteUser} className="p-6">
<h2 className="text-lg font-medium text-gray-900">
Are you sure you want to delete your account?
</h2>
<p className="mt-1 text-sm text-gray-600">
Once your account is deleted, all of its resources and data will be permanently deleted. Please
enter your password to confirm you would like to permanently delete your account.
</p>
<div className="mt-6">
<InputLabel htmlFor="password" value="Password" className="sr-only" />
<TextInput
id="password"
type="password"
name="password"
ref={passwordInput}
value={data.password}
onChange={(e) => setData('password', e.target.value)}
className="mt-1 block w-3/4"
isFocused
placeholder="Password"
/>
<InputError message={errors.password} className="mt-2" />
</div>
<div className="mt-6 flex justify-end">
<SecondaryButton onClick={closeModal}>Cancel</SecondaryButton>
<DangerButton className="ml-3" disabled={processing}>
Delete Account
</DangerButton>
</div>
</form>
</Modal>
</section>
);
}

View File

@@ -0,0 +1,113 @@
import { useRef } from 'react';
import InputError from '@/Components/InputError';
import InputLabel from '@/Components/InputLabel';
import PrimaryButton from '@/Components/PrimaryButton';
import TextInput from '@/Components/TextInput';
import { useForm } from '@inertiajs/react';
import { Transition } from '@headlessui/react';
export default function UpdatePasswordForm({ className = '' }) {
const passwordInput = useRef();
const currentPasswordInput = useRef();
const { data, setData, errors, put, reset, processing, recentlySuccessful } = useForm({
current_password: '',
password: '',
password_confirmation: '',
});
const updatePassword = (e) => {
e.preventDefault();
put(route('password.update'), {
preserveScroll: true,
onSuccess: () => reset(),
onError: (errors) => {
if (errors.password) {
reset('password', 'password_confirmation');
passwordInput.current.focus();
}
if (errors.current_password) {
reset('current_password');
currentPasswordInput.current.focus();
}
},
});
};
return (
<section className={className}>
<header>
<h2 className="text-lg font-medium text-gray-900">Update Password</h2>
<p className="mt-1 text-sm text-gray-600">
Ensure your account is using a long, random password to stay secure.
</p>
</header>
<form onSubmit={updatePassword} className="mt-6 space-y-6">
<div>
<InputLabel htmlFor="current_password" value="Current Password" />
<TextInput
id="current_password"
ref={currentPasswordInput}
value={data.current_password}
onChange={(e) => setData('current_password', e.target.value)}
type="password"
className="mt-1 block w-full"
autoComplete="current-password"
/>
<InputError message={errors.current_password} className="mt-2" />
</div>
<div>
<InputLabel htmlFor="password" value="New Password" />
<TextInput
id="password"
ref={passwordInput}
value={data.password}
onChange={(e) => setData('password', e.target.value)}
type="password"
className="mt-1 block w-full"
autoComplete="new-password"
/>
<InputError message={errors.password} className="mt-2" />
</div>
<div>
<InputLabel htmlFor="password_confirmation" value="Confirm Password" />
<TextInput
id="password_confirmation"
value={data.password_confirmation}
onChange={(e) => setData('password_confirmation', e.target.value)}
type="password"
className="mt-1 block w-full"
autoComplete="new-password"
/>
<InputError message={errors.password_confirmation} className="mt-2" />
</div>
<div className="flex items-center gap-4">
<PrimaryButton disabled={processing}>Save</PrimaryButton>
<Transition
show={recentlySuccessful}
enter="transition ease-in-out"
enterFrom="opacity-0"
leave="transition ease-in-out"
leaveTo="opacity-0"
>
<p className="text-sm text-gray-600">Saved.</p>
</Transition>
</div>
</form>
</section>
);
}

View File

@@ -0,0 +1,103 @@
import InputError from '@/Components/InputError';
import InputLabel from '@/Components/InputLabel';
import PrimaryButton from '@/Components/PrimaryButton';
import TextInput from '@/Components/TextInput';
import { Link, useForm, usePage } from '@inertiajs/react';
import { Transition } from '@headlessui/react';
export default function UpdateProfileInformation({ mustVerifyEmail, status, className = '' }) {
const user = usePage().props.auth.user;
const { data, setData, patch, errors, processing, recentlySuccessful } = useForm({
name: user.name,
email: user.email,
});
const submit = (e) => {
e.preventDefault();
patch(route('profile.update'));
};
return (
<section className={className}>
<header>
<h2 className="text-lg font-medium text-gray-900">Profile Information</h2>
<p className="mt-1 text-sm text-gray-600">
Update your account's profile information and email address.
</p>
</header>
<form onSubmit={submit} className="mt-6 space-y-6">
<div>
<InputLabel htmlFor="name" value="Name" />
<TextInput
id="name"
className="mt-1 block w-full"
value={data.name}
onChange={(e) => setData('name', e.target.value)}
required
isFocused
autoComplete="name"
/>
<InputError className="mt-2" message={errors.name} />
</div>
<div>
<InputLabel htmlFor="email" value="Email" />
<TextInput
id="email"
type="email"
className="mt-1 block w-full"
value={data.email}
onChange={(e) => setData('email', e.target.value)}
required
autoComplete="username"
/>
<InputError className="mt-2" message={errors.email} />
</div>
{mustVerifyEmail && user.email_verified_at === null && (
<div>
<p className="text-sm mt-2 text-gray-800">
Your email address is unverified.
<Link
href={route('verification.send')}
method="post"
as="button"
className="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Click here to re-send the verification email.
</Link>
</p>
{status === 'verification-link-sent' && (
<div className="mt-2 font-medium text-sm text-green-600">
A new verification link has been sent to your email address.
</div>
)}
</div>
)}
<div className="flex items-center gap-4">
<PrimaryButton disabled={processing}>Save</PrimaryButton>
<Transition
show={recentlySuccessful}
enter="transition ease-in-out"
enterFrom="opacity-0"
leave="transition ease-in-out"
leaveTo="opacity-0"
>
<p className="text-sm text-gray-600">Saved.</p>
</Transition>
</div>
</form>
</section>
);
}

View File

@@ -0,0 +1,52 @@
import Layout from '@/Layouts/Layout';
import Searchbar from '@/Components/Searchbar';
import CreateButton from '@/Components/CreateButton';
import { useState } from 'react'
import { router } from '@inertiajs/react'
export default function Index({ products, links, categories }){
let [createOpen, setCreateOpen] = useState(false);
function handleCancel(){
setCreateOpen(false);
}
function handleCreateClick(){
setCreateOpen(true);
}
function handleCreate(){
setCreateOpen(false);
router.refresh();
}
const product_list = products.map((product) => (
<div className="flex flex-col items-center justify-center bg-white rounded-lg w-full h-full">
{product.images[0] ? <img src={ product.images[0].thumbnail } alt={ product.images[0].alt } className="h-52 w-full object-cover rounded-t-lg shadow-md" /> : null}
<div className="p-4 py-6 flex flex-col items-center justify-center space-y-4">
<span className="text-xl">{product.title}</span>
<span className="text-gray-600 text-center">{product.description}</span>
</div>
</div>
));
return (
<div className="relative flex flex-col h-full w-full space-y-6">
{createOpen ? <div className="flex items-center justify-center absolute top-0 z-10 backdrop-blur h-full w-full rounded-lg backdrop-brightness-75">
<ProductForm onCancel = {handleCancel} categories={ categories }/>
</div> : ''}
<div className="flex justify-between h-fit">
<Searchbar />
<CreateButton onClick={ handleCreateClick } title="افزودن محصول"/>
</div>
<div className="grid grid-cols-4 gap-8">
{product_list}
</div>
<ProductTable items={ products } links={ links } title="محصولات" />
</div>
);
}
Index.layout = page => <Layout children={page} />