mirror of
https://github.com/vercel/commerce.git
synced 2025-07-26 19:51:23 +00:00
🎨 styles: shipping method
:%s
This commit is contained in:
@@ -9,6 +9,7 @@ import PaymentInfoForm from './components/PaymentInfoForm/PaymentInfoForm'
|
||||
import ShippingInfoForm from './components/ShippingInfoForm/ShippingInfoForm'
|
||||
interface CheckoutInfoProps {
|
||||
onViewCart: () => void
|
||||
currency?: string
|
||||
}
|
||||
|
||||
enum CheckoutStep {
|
||||
@@ -17,7 +18,7 @@ enum CheckoutStep {
|
||||
PaymentInfo = 3,
|
||||
}
|
||||
|
||||
const CheckoutInfo = ({ onViewCart }: CheckoutInfoProps) => {
|
||||
const CheckoutInfo = ({ onViewCart, currency = "" }: CheckoutInfoProps) => {
|
||||
const [activeStep, setActiveStep] = useState(1)
|
||||
const [doneSteps, setDoneSteps] = useState<CheckoutStep[]>([])
|
||||
const { order } = useGetActiveOrder()
|
||||
@@ -101,7 +102,7 @@ const CheckoutInfo = ({ onViewCart }: CheckoutInfoProps) => {
|
||||
{
|
||||
id: CheckoutStep.ShippingInfo,
|
||||
title: 'Shipping Information',
|
||||
form: <ShippingInfoForm onConfirm={onConfirm} id={CheckoutStep.ShippingInfo} activeStep={activeStep} />,
|
||||
form: <ShippingInfoForm onConfirm={onConfirm} id={CheckoutStep.ShippingInfo} activeStep={activeStep} currency={currency} />,
|
||||
},
|
||||
{
|
||||
id: CheckoutStep.PaymentInfo,
|
||||
|
@@ -18,7 +18,7 @@ const ChekoutNotePolicy = memo(() => {
|
||||
{
|
||||
<Link href={ROUTE.PRIVACY_POLICY}>
|
||||
<a>
|
||||
<strong>privacy policy </strong>
|
||||
<strong>privacy policy</strong>
|
||||
</a>
|
||||
</Link>
|
||||
}
|
||||
|
@@ -24,22 +24,5 @@
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
.method{
|
||||
width: 100%;
|
||||
height: 5.6rem;
|
||||
padding: 1.6rem;
|
||||
border-radius: 0.8rem;
|
||||
@apply flex justify-between items-center border border-solid border-line bg-gray;
|
||||
.left{
|
||||
@apply flex;
|
||||
.name{
|
||||
margin-left: 1.6rem;
|
||||
color: var(--text-active);
|
||||
}
|
||||
}
|
||||
.price{
|
||||
font-weight: bold;
|
||||
color: var(--text-active);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -3,17 +3,19 @@ import React, { useEffect, useRef } from 'react'
|
||||
import { ButtonCommon, InputFiledInForm, SelectFieldInForm } from 'src/components/common'
|
||||
import { useMessage } from 'src/components/contexts'
|
||||
import { useAvailableCountries, useSetOrderShippingAddress } from 'src/components/hooks/order'
|
||||
import { Shipping } from 'src/components/icons'
|
||||
import { LANGUAGE } from 'src/utils/language.utils'
|
||||
import { CustomInputCommon } from 'src/utils/type.utils'
|
||||
import * as Yup from 'yup'
|
||||
import ChekoutNotePolicy from '../ChekoutNotePolicy/ChekoutNotePolicy'
|
||||
import ShippingMethod from '../ShippingMethod/ShippingMethod'
|
||||
import s from './ShippingInfoForm.module.scss'
|
||||
|
||||
interface ShippingInfoFormProps {
|
||||
id: number
|
||||
activeStep: number
|
||||
onConfirm: (id: number) => void
|
||||
currency: string
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +33,7 @@ const displayingErrorMessagesSchema = Yup.object().shape({
|
||||
const DEFAULT_COUNTRY_CODE = 'MY'
|
||||
const DEFAULT_PROVINCE = 'Sabah'
|
||||
|
||||
// TODO: update data
|
||||
const provinceOptions = [
|
||||
{
|
||||
name: 'Hồ Chí Minh',
|
||||
@@ -46,7 +49,7 @@ const provinceOptions = [
|
||||
},
|
||||
]
|
||||
|
||||
const ShippingInfoForm = ({ onConfirm, id, activeStep }: ShippingInfoFormProps) => {
|
||||
const ShippingInfoForm = ({ onConfirm, id, activeStep , currency}: ShippingInfoFormProps) => {
|
||||
const addressRef = useRef<CustomInputCommon>(null)
|
||||
const { setOrderShippingAddress, loading } = useSetOrderShippingAddress()
|
||||
const { showMessageError } = useMessage()
|
||||
@@ -59,10 +62,7 @@ const ShippingInfoForm = ({ onConfirm, id, activeStep }: ShippingInfoFormProps)
|
||||
}, [activeStep])
|
||||
|
||||
const handleSubmit = (values: any) => {
|
||||
console.log("values: ", values)
|
||||
setOrderShippingAddress(values, onSubmitCalBack)
|
||||
|
||||
// onConfirm && onConfirm(id)
|
||||
}
|
||||
|
||||
const onSubmitCalBack = (isSuccess: boolean, msg?: string) => {
|
||||
@@ -176,21 +176,7 @@ const ShippingInfoForm = ({ onConfirm, id, activeStep }: ShippingInfoFormProps)
|
||||
onEnter={isValid ? submitForm : undefined}
|
||||
/>
|
||||
</div>
|
||||
<div className={s.method}>
|
||||
<div className={s.left}>
|
||||
<div className={s.icon}>
|
||||
<Shipping />
|
||||
</div>
|
||||
<div className={s.name}>
|
||||
Standard Delivery Method
|
||||
</div>
|
||||
</div>
|
||||
<div className={s.right}>
|
||||
<div className={s.price}>
|
||||
Free
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ShippingMethod currency={currency}/>
|
||||
<div className={s.bottom}>
|
||||
<ChekoutNotePolicy />
|
||||
<ButtonCommon HTMLType='submit' loading={loading} size="large">
|
||||
|
@@ -0,0 +1,39 @@
|
||||
.shippingMethod {
|
||||
@apply relative;
|
||||
.method {
|
||||
@apply w-full flex justify-between items-center border border-solid border-line bg-gray cursor-pointer;
|
||||
height: 5.6rem;
|
||||
padding: 1.6rem;
|
||||
border-radius: 0.8rem;
|
||||
.left {
|
||||
@apply flex;
|
||||
.name {
|
||||
margin-left: 1.6rem;
|
||||
color: var(--text-active);
|
||||
}
|
||||
}
|
||||
.price {
|
||||
font-weight: bold;
|
||||
color: var(--text-active);
|
||||
}
|
||||
}
|
||||
|
||||
.options {
|
||||
@apply absolute transition-all duration-200 overflow-hidden;
|
||||
transform: translateX(-100%);
|
||||
opacity: 0;
|
||||
margin-top: 0.8rem;
|
||||
top: 6rem;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background: var(--white);
|
||||
border: 1px solid var(--border-line);
|
||||
border-radius: 0.8rem;
|
||||
&.show {
|
||||
z-index: 10;
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
position: initial;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,94 @@
|
||||
import { ShippingMethodQuote } from '@framework/schema'
|
||||
import classNames from 'classnames'
|
||||
import React, { memo, useState } from 'react'
|
||||
import { useMessage } from 'src/components/contexts'
|
||||
import { useSetOrderShippingMethod } from 'src/components/hooks/order'
|
||||
import { Shipping } from 'src/components/icons'
|
||||
import s from './ShippingMethod.module.scss'
|
||||
import ShippingMethodItem from './ShippingMethodItem/ShippingMethodItem'
|
||||
|
||||
const MOCKUP_DATA = [
|
||||
{
|
||||
"id": "1",
|
||||
"name": "Standard Shipping",
|
||||
"description": "",
|
||||
"price": 0,
|
||||
"priceWithTax": 0,
|
||||
"code": "standard-shipping"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"name": "Express Shipping",
|
||||
"description": "",
|
||||
"price": 1000,
|
||||
"priceWithTax": 1000,
|
||||
"code": "express-shipping"
|
||||
}
|
||||
]
|
||||
interface Props {
|
||||
currency: string
|
||||
}
|
||||
|
||||
const ShippingMethod = memo(({ currency }: Props) => {
|
||||
const { setOrderShippingMethod } = useSetOrderShippingMethod()
|
||||
const [selectedValue, setSelectedValue] = useState<ShippingMethodQuote>(MOCKUP_DATA[0])
|
||||
const { showMessageError } = useMessage()
|
||||
const [isShowOptions, setIsShowOptions] = useState<boolean>(false)
|
||||
|
||||
const onChange = (id: string) => {
|
||||
const newValue = MOCKUP_DATA.find(item => item.id === id)
|
||||
if (newValue) {
|
||||
setSelectedValue(newValue)
|
||||
if (newValue?.id) {
|
||||
setOrderShippingMethod(newValue?.id, onSubmitCalBack)
|
||||
}
|
||||
}
|
||||
setIsShowOptions(false)
|
||||
}
|
||||
|
||||
const onSubmitCalBack = (isSuccess: boolean, msg?: string) => {
|
||||
if (!isSuccess) {
|
||||
showMessageError(msg)
|
||||
}
|
||||
}
|
||||
|
||||
const onCollapseOptions = () => {
|
||||
setIsShowOptions(!isShowOptions)
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className={s.shippingMethod}>
|
||||
<div className={s.method} onClick={onCollapseOptions}>
|
||||
<div className={s.left}>
|
||||
<div className={s.icon}>
|
||||
<Shipping />
|
||||
</div>
|
||||
<div className={s.name}>
|
||||
{selectedValue.name}
|
||||
</div>
|
||||
</div>
|
||||
<div className={s.right}>
|
||||
<div className={s.price}>
|
||||
{selectedValue.price ? `${selectedValue.price / 100} ${currency}` : "Free"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={classNames(s.options, { [s.show]: isShowOptions })}>
|
||||
<ul>
|
||||
{MOCKUP_DATA.map(item => <ShippingMethodItem
|
||||
key={item.id}
|
||||
id={item.id}
|
||||
name={item.name}
|
||||
price={item.price}
|
||||
currency={currency}
|
||||
onSelect={onChange}
|
||||
/>)}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
ShippingMethod.displayName = 'ShippingMethod'
|
||||
export default ShippingMethod
|
@@ -0,0 +1,19 @@
|
||||
.shippingMethodItem {
|
||||
@apply flex justify-between items-center cursor-pointer transition-all duration-200;
|
||||
width: 100%;
|
||||
padding: 1.6rem;
|
||||
&:hover {
|
||||
@apply bg-gray;
|
||||
}
|
||||
.left {
|
||||
@apply flex;
|
||||
.name {
|
||||
margin-left: 1.6rem;
|
||||
color: var(--text-active);
|
||||
}
|
||||
}
|
||||
.price {
|
||||
font-weight: bold;
|
||||
color: var(--text-active);
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
import React, { memo } from 'react'
|
||||
import s from './ShippingMethodItem.module.scss'
|
||||
|
||||
interface Props {
|
||||
id: string
|
||||
name: string
|
||||
price: number
|
||||
currency: string
|
||||
onSelect: (id: string) => void
|
||||
}
|
||||
|
||||
const ShippingMethodItem = memo(({ id, name, price, currency, onSelect }: Props) => {
|
||||
const handleSelect = () => {
|
||||
onSelect(id)
|
||||
}
|
||||
return (
|
||||
<li className={s.shippingMethodItem} key={id} onClick={handleSelect}>
|
||||
<div className={s.name}>
|
||||
{name}
|
||||
</div>
|
||||
<div className={s.price}>
|
||||
{price ? `${price / 100} ${currency}` : "Free"}
|
||||
</div>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
|
||||
ShippingMethodItem.displayName = 'ShippingMethodItem'
|
||||
export default ShippingMethodItem
|
@@ -24,7 +24,7 @@ const CheckoutPage = ({ }: CheckoutPageProps) => {
|
||||
return (
|
||||
<div className={s.warrper}>
|
||||
<MessageCommon messages={messages} onRemove={removeMessage} />
|
||||
<div className={s.left}><CheckoutInfo onViewCart={onViewCart} /></div>
|
||||
<div className={s.left}><CheckoutInfo onViewCart={onViewCart} currency={order?.currency.code}/></div>
|
||||
<div className={s.right}><CheckoutBill data={order} /></div>
|
||||
<div className={classNames({ [s.mobile]: true, [s.isShow]: isShow })}>
|
||||
<div className={s.modal}>
|
||||
|
Reference in New Issue
Block a user