add: checkout page
This commit is contained in:
@@ -6,7 +6,7 @@ import React from 'react'
|
|||||||
function DialogsLayout({ children }: { children: React.ReactNode }) {
|
function DialogsLayout({ children }: { children: React.ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<ClientSideWrapper>
|
<ClientSideWrapper>
|
||||||
<main className='h-full w-full bg-container lg:bg-background pt-4 pb-6 px-6'>
|
<main className='h-full w-full overflow-y-auto noscrollbar bg-container lg:bg-background pt-4 pb-6 px-6'>
|
||||||
{children}
|
{children}
|
||||||
</main>
|
</main>
|
||||||
</ClientSideWrapper>
|
</ClientSideWrapper>
|
||||||
|
|||||||
@@ -0,0 +1,316 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import AnimatedBottomSheet from '@/components/bottomsheet/AnimatedBottomSheet';
|
||||||
|
import Button from '@/components/button/PrimaryButton';
|
||||||
|
import Combobox, { ComboboxOption } from '@/components/combobox/Combobox';
|
||||||
|
import InputField from '@/components/input/InputField';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { ArrowLeft, Box, Card, Cup, Icon, Shop, Ticket, TicketDiscount, TruckTick, Wallet2 } from 'iconsax-react';
|
||||||
|
import { ChevronLeft, MinusIcon, PlusIcon } from 'lucide-react';
|
||||||
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
|
import React, { useCallback, useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
type Params = {
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function OrderDetailInex() {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const params = useParams<Params>();
|
||||||
|
const { t } = useTranslation('parallels', { keyPrefix: 'OrderDetail' });
|
||||||
|
const router = useRouter();
|
||||||
|
const [deliveryType, setDeliveryType] = React.useState<string>('0');
|
||||||
|
const [paymentType, setPaymentType] = React.useState<string>('0');
|
||||||
|
const [couponType, setCouponType] = React.useState<string>('0');
|
||||||
|
const [couponCode, setCouponCode] = React.useState<string>('');
|
||||||
|
const [cartModal, setCartModal] = React.useState<boolean>(false);
|
||||||
|
const [couponCodeError, setCouponCodeError] = React.useState<string>(''); // TODO: handle coupon code error
|
||||||
|
const [tableNumber, setTableNumber] = useState(0) // TODO: must be set to table number
|
||||||
|
const incrementTableNumber = () => setTableNumber((prev) => prev + 1); // TODO: must be set to table number
|
||||||
|
const decrementTableNumber = () => setTableNumber((prev) => prev - 1); // TODO: must be set to table number
|
||||||
|
const address = "اراک، مصطفی خمینی، خیابان سینا کوچه چمران ساختمان شهرزاد"
|
||||||
|
|
||||||
|
const deliveryOptions: Array<ComboboxOption> = [
|
||||||
|
{ id: '0', title: t("SectionShipping.InputDeliveryType.Options.Delivery"), icon: TruckTick },
|
||||||
|
{ id: '1', title: t("SectionShipping.InputDeliveryType.Options.Serve"), icon: Shop },
|
||||||
|
{ id: '2', title: t("SectionShipping.InputDeliveryType.Options.Pickup"), icon: Box },
|
||||||
|
];
|
||||||
|
|
||||||
|
const paymentOptions: Array<{ id: string, label: string, icon: Icon }> = [
|
||||||
|
{ id: '0', label: t("SectionPayment.InputPaymentType.Options.Online"), icon: Card },
|
||||||
|
{ id: '1', label: t("SectionPayment.InputPaymentType.Options.CashOnDelivery"), icon: Wallet2 },
|
||||||
|
];
|
||||||
|
|
||||||
|
const couponOptions: Array<{ id: string, label: string, icon: Icon }> = [
|
||||||
|
{ id: '0', label: t("SectionCoupon.InputCouponType.Options.Discount"), icon: Cup },
|
||||||
|
{ id: '1', label: t("SectionCoupon.InputCouponType.Options.GiftCard"), icon: Ticket },
|
||||||
|
];
|
||||||
|
|
||||||
|
const couponDropdownOptions: Array<ComboboxOption> = [
|
||||||
|
{ id: '0', title: t("SectionCoupon.InputCouponCode.Options.Default") },
|
||||||
|
{ id: '1', title: "Something" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const changeDeliveryType = useCallback((id: string) => {
|
||||||
|
setDeliveryType(id);
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const changePaymentType = useCallback((id: string) => {
|
||||||
|
setPaymentType(id);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const changeCouponType = useCallback((id: string) => {
|
||||||
|
setCouponCode('');
|
||||||
|
setCouponCodeError('');
|
||||||
|
setCouponType(id);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const changeCouponCode = useCallback((id: string) => {
|
||||||
|
if (id === '0') {
|
||||||
|
setCouponCode('');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setCouponCode(id);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const toggleCartModal = useCallback(() => {
|
||||||
|
setCartModal((prev) => !prev);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const addressSection = () => {
|
||||||
|
if (deliveryType !== '0') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
className="bg-container rounded-container box-shadow-normal p-4">
|
||||||
|
<div className="py-3">
|
||||||
|
<div className='w-full flex justify-between items-center gap-2'>
|
||||||
|
<h3 className="text-sm2 font-medium leading-5 inline-block">{t("SectionAddress.Title")}</h3>
|
||||||
|
<button
|
||||||
|
className='text-sm2 text-primary cursor-pointer'
|
||||||
|
onClick={() => { /* Handle address change */ }}
|
||||||
|
>
|
||||||
|
{t("SectionAddress.ButtonChangeAddress")}
|
||||||
|
<ChevronLeft className='inline-block mr-1 mb-0.5 stroke-primary' size='16' />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<p className='mt-6 text-sm2'>
|
||||||
|
{address}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const tableSection = () => {
|
||||||
|
if (deliveryType !== '1') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
className="bg-container rounded-container box-shadow-normal p-4 py-2">
|
||||||
|
<div className="py-3">
|
||||||
|
<div className='w-full grid grid-cols-2 justify-between items-center gap-2'>
|
||||||
|
<h3 className="text-sm2 font-medium leading-5 inline-block">{t("SectionTable.Title")}</h3>
|
||||||
|
|
||||||
|
<div className='w-full flex justify-end'>
|
||||||
|
<motion.div
|
||||||
|
whileTap={{ scale: 1.05 }}
|
||||||
|
className="bg-background active:drop-shadow-xs max-w-[132px] rounded-md w-full h-8 inline-flex p-1 justify-between items-center gap-2"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
onClick={() => incrementTableNumber()}
|
||||||
|
className="bg-white hover:bg-white/60 size-6 place-items-center active:bg-white/30 rounded-sm"
|
||||||
|
>
|
||||||
|
<PlusIcon size={16} />
|
||||||
|
</button>
|
||||||
|
<motion.div
|
||||||
|
key={tableNumber}
|
||||||
|
initial={{ scale: 1 }}
|
||||||
|
animate={{ scale: [1.2, 0.95, 1] }}
|
||||||
|
transition={{ duration: 0.3 }}
|
||||||
|
className="text-sm2 pt-0.5 font-semibold"
|
||||||
|
>
|
||||||
|
{tableNumber}
|
||||||
|
</motion.div>
|
||||||
|
<button
|
||||||
|
onClick={() => decrementTableNumber()}
|
||||||
|
className="bg-white hover:bg-white/60 size-6 place-items-center active:bg-white/30 rounded-sm"
|
||||||
|
>
|
||||||
|
<MinusIcon size={16} />
|
||||||
|
</button>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='h-full bg-inherit flex flex-col gap-5'>
|
||||||
|
<div className='grid grid-cols-3 items-center py-4 '>
|
||||||
|
<span></span>
|
||||||
|
<h1 className='text-sm2 place-self-center font-medium'>{t("Heading")}</h1>
|
||||||
|
<ArrowLeft
|
||||||
|
className='cursor-pointer place-self-end'
|
||||||
|
size='24'
|
||||||
|
color='currentColor'
|
||||||
|
onClick={() => { router.back() }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<section
|
||||||
|
className="bg-container rounded-container box-shadow-normal p-4">
|
||||||
|
<div className="py-3">
|
||||||
|
<h3 className="text-sm2 font-medium leading-5">{t("SectionShipping.Title")}</h3>
|
||||||
|
<Combobox
|
||||||
|
className='relative mt-6'
|
||||||
|
icon={Box}
|
||||||
|
title=''
|
||||||
|
searchable={false}
|
||||||
|
options={deliveryOptions}
|
||||||
|
selectedId={deliveryType}
|
||||||
|
onSelectionChange={(e, i) => changeDeliveryType(String(i))}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{addressSection()}
|
||||||
|
{tableSection()}
|
||||||
|
|
||||||
|
<section
|
||||||
|
className="bg-container rounded-container box-shadow-normal p-4">
|
||||||
|
<div className="py-3">
|
||||||
|
<h3 className="text-sm2 font-medium leading-5">{t("SectionPayment.Title")}</h3>
|
||||||
|
|
||||||
|
<div className='flex flex-col gap-5 mt-6'>
|
||||||
|
{paymentOptions.map(({ id, label, icon: Icon }) => (
|
||||||
|
<div key={id} className='flex items-center'>
|
||||||
|
|
||||||
|
<label className='flex items-center gap-2 w-full' htmlFor={`paymentMethod${id}`}>
|
||||||
|
<Icon
|
||||||
|
size={16}
|
||||||
|
color='currentColor'
|
||||||
|
className='mr-2'
|
||||||
|
/>
|
||||||
|
<span className='text-xs mt-0.5'>{label}</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
checked={paymentType === id}
|
||||||
|
onChange={() => changePaymentType(id)}
|
||||||
|
type='radio'
|
||||||
|
name='paymentMethod'
|
||||||
|
id={`paymentMethod${id}`}
|
||||||
|
className='size-4 accent-primary' />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section
|
||||||
|
className="bg-container rounded-container box-shadow-normal p-4">
|
||||||
|
<div className="py-3">
|
||||||
|
<h3 className="text-sm2 font-medium leading-5">{t("SectionCoupon.Title")}</h3>
|
||||||
|
|
||||||
|
<div className='flex flex-col gap-5 mt-6'>
|
||||||
|
{couponOptions.map(({ id, label, icon: Icon }) => (
|
||||||
|
<div key={id} className='flex items-center'>
|
||||||
|
|
||||||
|
<label className='flex items-center gap-2 w-full' htmlFor={`couponType${id}`}>
|
||||||
|
<Icon
|
||||||
|
size={16}
|
||||||
|
color='currentColor'
|
||||||
|
className='mr-2'
|
||||||
|
/>
|
||||||
|
<span className='text-xs mt-0.5'>{label}</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
checked={couponType === id}
|
||||||
|
onChange={() => changeCouponType(id)}
|
||||||
|
type='radio'
|
||||||
|
name='couponType'
|
||||||
|
id={`couponType${id}`}
|
||||||
|
className='size-4 accent-primary' />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Combobox
|
||||||
|
className={clsx(
|
||||||
|
'relative mt-6',
|
||||||
|
couponType === '0' ? 'block' : 'hidden',
|
||||||
|
couponCode.length === 0 && 'text-border **:stroke-border'
|
||||||
|
)}
|
||||||
|
icon={TicketDiscount}
|
||||||
|
placeholder={t("SectionCoupon.InputCouponCode.Placeholder")}
|
||||||
|
title=''
|
||||||
|
searchable={false}
|
||||||
|
options={couponDropdownOptions}
|
||||||
|
selectedId={couponCode}
|
||||||
|
onSelectionChange={(e, i) => changeCouponCode(String(i))}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InputField
|
||||||
|
autoComplete='off'
|
||||||
|
className={clsx(
|
||||||
|
'relative mt-6',
|
||||||
|
couponType === '1' ? '' : 'hidden!',
|
||||||
|
couponCodeError.trim() === 'valid' && 'text-emerald-400 **:stroke-emerald-400 ring ring-emerald-400'
|
||||||
|
)}
|
||||||
|
placeholder={t("SectionCoupon.InputCouponCode.Placeholder")}
|
||||||
|
htmlFor={'couponCode'}
|
||||||
|
onChange={(e) => changeCouponCode(e.target.value)}
|
||||||
|
value={couponCode}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section
|
||||||
|
className="">
|
||||||
|
<div className="py-3 pb-10">
|
||||||
|
<div className='w-full flex justify-between items-center gap-2'>
|
||||||
|
<h3 className="text-sm2 font-medium leading-5 inline-block">{t("SectionSummary.Title")}</h3>
|
||||||
|
<button
|
||||||
|
className='text-sm2 text-primary cursor-pointer'
|
||||||
|
onClick={toggleCartModal}
|
||||||
|
>
|
||||||
|
{t("SectionSummary.ButtonViewCart")}
|
||||||
|
<ChevronLeft className='inline-block mr-1 mb-0.5 stroke-primary' size='16' />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className='mt-6 text-sm2 grid grid-cols-2 gap-4'>
|
||||||
|
<span className=''>{t("SectionSummary.SumOfItemsLabel")}</span>
|
||||||
|
<span className='font-medium place-self-end '>100,000 T</span>
|
||||||
|
<span className=''>{t("SectionSummary.DeliveryLabel")}</span>
|
||||||
|
<span className='font-medium place-self-end '>20,000 T</span>
|
||||||
|
<span className='text-emerald-600'>{t("SectionSummary.DiscountLabel")}</span>
|
||||||
|
<span className='font-medium place-self-end text-emerald-600'>10,000 T</span>
|
||||||
|
<span className='font-medium '>{t("SectionSummary.TotalLabel")}</span>
|
||||||
|
<span className='font-bold place-self-end'>110,000 T</span>
|
||||||
|
</div>
|
||||||
|
<Button className='mt-6'>
|
||||||
|
{t("ButtonSubmit")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<AnimatedBottomSheet
|
||||||
|
title={t("CartModal.Title")}
|
||||||
|
visible={cartModal}
|
||||||
|
onClick={toggleCartModal}
|
||||||
|
>
|
||||||
|
<div></div>
|
||||||
|
</AnimatedBottomSheet>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OrderDetailInex
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
import React, { useState, useEffect, useRef } from 'react';
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
import ArrowDownIcon from '../icons/ArrowDownIcon';
|
|
||||||
import { motion, Variants } from 'framer-motion';
|
import { motion, Variants } from 'framer-motion';
|
||||||
import { SearchNormal } from 'iconsax-react';
|
import { Icon, SearchNormal } from 'iconsax-react';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
import { ChevronDown } from 'lucide-react';
|
||||||
|
|
||||||
export interface ComboboxOption {
|
export interface ComboboxOption {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
icon?: Icon;
|
||||||
label?: string;
|
label?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15,10 +17,12 @@ type Props = {
|
|||||||
expanded?: boolean;
|
expanded?: boolean;
|
||||||
selectedId: string;
|
selectedId: string;
|
||||||
searchable?: boolean;
|
searchable?: boolean;
|
||||||
|
placeholder?: string;
|
||||||
|
icon?: React.ElementType;
|
||||||
onSelectionChange: (e: React.MouseEvent<HTMLDivElement, MouseEvent>, index: number) => void,
|
onSelectionChange: (e: React.MouseEvent<HTMLDivElement, MouseEvent>, index: number) => void,
|
||||||
} & React.HTMLAttributes<HTMLDivElement>
|
} & React.HTMLAttributes<HTMLDivElement>
|
||||||
|
|
||||||
function Combobox({ title, options, expanded, selectedId, searchable = true, onSelectionChange, ...props }: Props) {
|
function Combobox({ title, options, placeholder, icon: Icon, expanded, selectedId, searchable = true, onSelectionChange, ...props }: Props) {
|
||||||
const [expand, setExpand] = useState(expanded);
|
const [expand, setExpand] = useState(expanded);
|
||||||
const [searchValue, setSearchValue] = useState('');
|
const [searchValue, setSearchValue] = useState('');
|
||||||
const boxRef = useRef<HTMLDivElement>(null);
|
const boxRef = useRef<HTMLDivElement>(null);
|
||||||
@@ -54,6 +58,13 @@ function Combobox({ title, options, expanded, selectedId, searchable = true, onS
|
|||||||
setExpand(false);
|
setExpand(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const selectedOption = options.find((x) => x.id === selectedId);
|
||||||
|
const activeIcon = selectedOption?.icon && React.createElement(selectedOption.icon, {
|
||||||
|
size: 16,
|
||||||
|
className: "inline-block mr-1 stroke-primary"
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
const variants: Variants = {
|
const variants: Variants = {
|
||||||
collapse: {
|
collapse: {
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
@@ -77,7 +88,12 @@ function Combobox({ title, options, expanded, selectedId, searchable = true, onS
|
|||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={boxRef} className={`relative ${props.className ?? ''}`} {...props}>
|
<div ref={boxRef}
|
||||||
|
className={clsx(
|
||||||
|
"relative",
|
||||||
|
props.className ?? '')}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
className="flex w-full h-11 items-center justify-end gap-2 px-3 py-4 relative bg-white/29 rounded-xl border border-solid border-neutral-200 cursor-pointer"
|
className="flex w-full h-11 items-center justify-end gap-2 px-3 py-4 relative bg-white/29 rounded-xl border border-solid border-neutral-200 cursor-pointer"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
@@ -97,17 +113,29 @@ function Combobox({ title, options, expanded, selectedId, searchable = true, onS
|
|||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="w-full text-sm2">
|
<div className="w-full text-sm2 flex items-center justify-start gap-3">
|
||||||
{options.find((x) => x.id === selectedId)?.title ?? ''}
|
{
|
||||||
|
activeIcon ? (
|
||||||
|
activeIcon
|
||||||
|
) : (
|
||||||
|
Icon && <Icon size={16} className="inline-block mr-1 stroke-primary" />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
<span className={clsx(
|
||||||
|
selectedOption?.title ? "mt-0.5" : "mt-1 text-sm font-light"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{selectedOption?.title ?? placeholder}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ArrowDownIcon data-expand={expand} className="transition-all duration-200 data-[expand=true]:rotate-x-180" />
|
<ChevronDown size={20} data-expand={expand} className="transition-all stroke-foreground duration-200 data-[expand=true]:rotate-x-180" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<motion.div
|
<motion.div
|
||||||
data-expand={expand}
|
data-expand={expand}
|
||||||
aria-hidden={!expand}
|
aria-hidden={!expand}
|
||||||
className="absolute top-full left-0 w-full mt-1 bg-white rounded-xl outline outline-solid outline-neutral-200 shadow-lg z-10"
|
className="absolute top-full left-0 w-full mt-1 text-foreground bg-white rounded-xl outline outline-solid outline-neutral-200 shadow-lg z-10"
|
||||||
role="listbox"
|
role="listbox"
|
||||||
aria-label={`${title} options`}
|
aria-label={`${title} options`}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
@@ -135,12 +163,18 @@ function Combobox({ title, options, expanded, selectedId, searchable = true, onS
|
|||||||
onClick={(e) => setSelection(e, i)}
|
onClick={(e) => setSelection(e, i)}
|
||||||
key={v.id}
|
key={v.id}
|
||||||
data-selected={v.id === selectedId}
|
data-selected={v.id === selectedId}
|
||||||
className="flex items-center justify-end px-2 py-1.5 cursor-pointer hover:bg-gray-50 rounded-md last:rounded-b-xl"
|
className="flex gap-3 items-center justify-end px-2 py-1 cursor-pointer hover:bg-gray-50 rounded-md last:rounded-b-xl"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
role="option"
|
role="option"
|
||||||
aria-selected
|
aria-selected
|
||||||
>
|
>
|
||||||
<span className="text-sm2 tracking-[0.13px] leading-5 w-full">{v.title}</span>
|
{
|
||||||
|
v?.icon && React.createElement(v.icon, {
|
||||||
|
size: 16,
|
||||||
|
className: "inline-block mr-1 stroke-primary"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
<span className="text-sm2 tracking-[0.13px] leading-5 w-full mt-1">{v.title}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ type Props = {
|
|||||||
|
|
||||||
function InputField({ onChange, htmlFor, labelText, children, valid = true, className, ...inputProps }: Props) {
|
function InputField({ onChange, htmlFor, labelText, children, valid = true, className, ...inputProps }: Props) {
|
||||||
return (
|
return (
|
||||||
<div className={`${className} ${valid ? 'border-border' : 'border-invalid'} h-11 inline-flex relative border px-3 w-full rounded-normal group focus-within:border`}>
|
<div
|
||||||
|
spellCheck={false}
|
||||||
|
className={`${className} ${valid ? 'border-border' : 'border-invalid'} h-11 inline-flex relative border px-3 w-full rounded-normal group focus-within:border`}>
|
||||||
<label
|
<label
|
||||||
className='absolute start-2 -top-2.5 px-2 bg-inherit text-[12px] text-foreground'
|
className='absolute start-2 -top-2.5 px-2 bg-inherit text-[12px] text-foreground'
|
||||||
htmlFor={htmlFor}>
|
htmlFor={htmlFor}>
|
||||||
|
|||||||
@@ -23,5 +23,83 @@
|
|||||||
"SumOfItemsLabel": "جمع خرید:",
|
"SumOfItemsLabel": "جمع خرید:",
|
||||||
"SumOfItemsValue": "{price} تومان",
|
"SumOfItemsValue": "{price} تومان",
|
||||||
"ButtonCheckout": "مشاهده فاکتور و پرداخت"
|
"ButtonCheckout": "مشاهده فاکتور و پرداخت"
|
||||||
|
},
|
||||||
|
"OrderDetail": {
|
||||||
|
"Heading": "ثبت نهایی",
|
||||||
|
"Description": "در صورت بروز مشکل در پرداخت، لطفا با ما تماس بگیرید.",
|
||||||
|
"SectionShipping": {
|
||||||
|
"Title": "روش تحویل",
|
||||||
|
"InputDeliveryType": {
|
||||||
|
"Label": "",
|
||||||
|
"Options": {
|
||||||
|
"Delivery": "ارسال با پیک",
|
||||||
|
"Serve": "سرو در رستوران",
|
||||||
|
"Pickup": "تحویل در محل"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SectionAddress": {
|
||||||
|
"Title": "آدرس",
|
||||||
|
"ButtonChangeAddress": "تغییر آدرس",
|
||||||
|
"InputAddressType": {
|
||||||
|
"Label": "نوع آدرس",
|
||||||
|
"Options": {
|
||||||
|
"Home": "آدرس منزل",
|
||||||
|
"Work": "آدرس محل کار",
|
||||||
|
"Other": "آدرس دیگر"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"InputAddressDetails": {
|
||||||
|
"Label": "",
|
||||||
|
"Placeholder": "خیابان ولیعصر، کوچه 12، پلاک 34"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SectionTable": {
|
||||||
|
"Title": "شماره میز"
|
||||||
|
},
|
||||||
|
"SectionPayment": {
|
||||||
|
"Title": "انتخاب شیوه پرداخت",
|
||||||
|
"InputPaymentType": {
|
||||||
|
"Label": "",
|
||||||
|
"Options": {
|
||||||
|
"Online": "پرداخت آنلاین درگاه بانکی",
|
||||||
|
"CashOnDelivery": "موجودی کیف پول"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SectionCoupon": {
|
||||||
|
"Title": "کوپن",
|
||||||
|
"InputCouponType": {
|
||||||
|
"Label": "نوع کوپن",
|
||||||
|
"Options": {
|
||||||
|
"Discount": "استفاده از امتیاز ها",
|
||||||
|
"GiftCard": "استفاده از کد تخفیف"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"InputCouponCode": {
|
||||||
|
"Label": "",
|
||||||
|
"Placeholder": "F12BB587",
|
||||||
|
"Options": {
|
||||||
|
"Default": "پیشفرض"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SectionSummary": {
|
||||||
|
"Title": "جزئیات پرداخت",
|
||||||
|
"Description": "لطفا قبل از پرداخت، اطلاعات زیر را بررسی کنید.",
|
||||||
|
"SumOfItemsLabel": "جمع خرید:",
|
||||||
|
"SumOfItemsValue": "{price} T",
|
||||||
|
"DeliveryLabel": "هزینه ارسال:",
|
||||||
|
"DeliveryValue": "{shipping} T",
|
||||||
|
"DiscountLabel": "تخفیف:",
|
||||||
|
"DiscountValue": "{discount} T",
|
||||||
|
"TotalLabel": "جمع کل:",
|
||||||
|
"TotalValue": "{total} T",
|
||||||
|
"ButtonViewCart": "مشاهده اقلام"
|
||||||
|
},
|
||||||
|
"CartModal": {
|
||||||
|
"Title": "اقلام سفارش"
|
||||||
|
},
|
||||||
|
"ButtonSubmit": "پرداخت"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user