From 65a30569ac57683a970249e1b8ac315c53cfbe58 Mon Sep 17 00:00:00 2001 From: "aton.xia" Date: Fri, 25 Nov 2022 15:46:18 +0800 Subject: [PATCH] feat: add delete and default modal --- .../src/components/B3ConfirmDialog.tsx | 13 +- .../src/components/B3TipsDialog.tsx | 103 ++++++++++++ apps/storefront/src/pages/address/Address.tsx | 123 +++++++------- .../address/components/AddressItemCard.tsx | 2 +- .../components/DeleteAddressDialog .tsx | 116 +++++++++++++ .../address/components/SetDefaultDialog.tsx | 153 ++++++++++++++++++ .../src/pages/address/shared/config.ts | 11 -- .../src/shared/service/b2b/graphql/address.ts | 50 ++++++ .../src/shared/service/b2b/index.ts | 4 + 9 files changed, 495 insertions(+), 80 deletions(-) create mode 100644 apps/storefront/src/components/B3TipsDialog.tsx create mode 100644 apps/storefront/src/pages/address/components/DeleteAddressDialog .tsx create mode 100644 apps/storefront/src/pages/address/components/SetDefaultDialog.tsx diff --git a/apps/storefront/src/components/B3ConfirmDialog.tsx b/apps/storefront/src/components/B3ConfirmDialog.tsx index d07b5b7b..4e1337fc 100644 --- a/apps/storefront/src/components/B3ConfirmDialog.tsx +++ b/apps/storefront/src/components/B3ConfirmDialog.tsx @@ -28,16 +28,15 @@ const Spinner = styled(CircularProgress)({ }) interface StyleButtonProps { - customConfirmColor?: string, - customConfirmHoverColor?: string, + customconfirmcolor?: string, + customconfirmhovercolor?: string, } const StyleButton = styled(Button)((props: StyleButtonProps) => ({ - textTransform: 'capitalize', - backgroundColor: props.customConfirmColor, + backgroundColor: props.customconfirmcolor, '&:hover': { - backgroundColor: props.customConfirmHoverColor, + backgroundColor: props.customconfirmhovercolor, }, })) @@ -167,8 +166,8 @@ export const B3ConfirmDialog = (props: B3ConfirmDialogProps) => { color={confirmColor} variant="contained" disabled={isConfirmDisabled} - customConfirmColor={customConfirmColor} - customConfirmHoverColor={customConfirmHoverColor} + customconfirmcolor={customConfirmColor} + customconfirmhovercolor={customConfirmHoverColor} > { isSpinning && ( diff --git a/apps/storefront/src/components/B3TipsDialog.tsx b/apps/storefront/src/components/B3TipsDialog.tsx new file mode 100644 index 00000000..414b98b5 --- /dev/null +++ b/apps/storefront/src/components/B3TipsDialog.tsx @@ -0,0 +1,103 @@ +import React, { + Dispatch, + ReactNode, + SetStateAction, +} from 'react' + +import { + Box, + Button, + Typography, +} from '@mui/material' +import HighlightOffIcon from '@mui/icons-material/HighlightOff' +import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline' +import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline' + +import styled from '@emotion/styled' + +import { + B3ConfirmDialog, +} from './B3ConfirmDialog' + +const TipsContent = styled(Box)({ + padding: '30px', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', +}) + +interface B3TipsDialogProps { + isOpen: boolean + setIsOpen: Dispatch> + onClose?: () => void, + children: ReactNode, + type?: 'success' | 'error' | 'warn' +} + +const icon = { + success: ( + + ), + error: ( + + ), + warn: ( + + ), +} + +export const B3TipsDialog = (props: B3TipsDialogProps) => { + const { + isOpen, + children, + setIsOpen, + onClose, + type = 'success', + } = props + + const handleClose = () => { + setIsOpen(false) + if (onClose) { + onClose() + } + } + + return ( + + + {icon[type]} + {children} + + + + ) +} diff --git a/apps/storefront/src/pages/address/Address.tsx b/apps/storefront/src/pages/address/Address.tsx index f8c68a5b..505a3874 100644 --- a/apps/storefront/src/pages/address/Address.tsx +++ b/apps/storefront/src/pages/address/Address.tsx @@ -1,9 +1,7 @@ import { Box, - Button, Typography, } from '@mui/material' -import HighlightOffIcon from '@mui/icons-material/HighlightOff' import { useEffect, @@ -11,8 +9,6 @@ import { useState, } from 'react' -import styled from '@emotion/styled' - import { useMobile, } from '@/hooks' @@ -21,6 +17,12 @@ import B3Filter from '../../components/filter/B3Filter' import { AddressItemCard, } from './components/AddressItemCard' +import { + SetDefaultDialog, +} from './components/SetDefaultDialog' +import { + DeleteAddressDialog, +} from './components/DeleteAddressDialog ' import { Pagination, B3Table, @@ -28,9 +30,10 @@ import { import { B3Sping, } from '@/components/spin/B3Sping' + import { - B3ConfirmDialog, -} from '@/components/B3ConfirmDialog' + B3TipsDialog, +} from '@/components/B3TipsDialog' import { GlobaledContext, @@ -42,21 +45,12 @@ import { import { filterFormConfig, - filterSortConfig, - filterPickerConfig, } from './shared/config' import { AddressItemType, } from '../../types/address' -const PermissionContent = styled(Box)({ - padding: '30px', - display: 'flex', - flexDirection: 'column', - alignItems: 'center', -}) - const Address = () => { const { state: { @@ -74,7 +68,7 @@ const Address = () => { const [pagination, setPagination] = useState({ offset: 0, count: 0, - first: 1, + first: 10, }) const [isMobile] = useMobile() @@ -144,9 +138,20 @@ const Address = () => { getAddressList(pagination, searchParams) } - const [editPermission, setEditPermission] = useState(false) + const updateAddressList = (isFirst: boolean = true) => { + getAddressList({ + ...pagination, + offset: isFirst ? 0 : pagination.offset, + }, searchParams) + } + + const [editPermission, setEditPermission] = useState(true) const [isOpenPermission, setIsOpenPermission] = useState(false) - const isAdmin = !role || role === 3 + const [isOpenSetDefault, setIsOpenSetDefault] = useState(false) + const [isOpenDelete, setIsOpenDelete] = useState(false) + const [currentAddress, setCurrentAddress] = useState() + + const isAdmin = !isB2BUser || !role || role === 3 const getEditPermission = () => { if (isAdmin) { @@ -163,7 +168,6 @@ const Address = () => { return false } if (!editPermission) { - console.log(1111) setIsOpenPermission(true) return false } @@ -186,17 +190,21 @@ const Address = () => { console.log('edit') } - const handleDelete = () => { + const handleDelete = (address: AddressItemType) => { if (!checkPermission()) { return } - // TODO show delete modal - console.log('delete') + setCurrentAddress({ + ...address, + }) + setIsOpenDelete(true) } - const handleSetDefault = () => { - // TODO show delete modal - console.log('setDefault') + const handleSetDefault = (address: AddressItemType) => { + setCurrentAddress({ + ...address, + }) + setIsOpenSetDefault(true) } const AddButtonConfig = { @@ -213,9 +221,6 @@ const Address = () => { }} > { isCustomRender isInfiniteScroll={isMobile} isLoading={isRequestLoading} + rowsPerPageOptions={[9, 18, 36]} renderItem={(row: AddressItemType) => ( { /> - - - - - Address add has been disabled by the system administrators - - - - - + + Address add has been disabled by the system administrators + + + + + + ) } diff --git a/apps/storefront/src/pages/address/components/AddressItemCard.tsx b/apps/storefront/src/pages/address/components/AddressItemCard.tsx index 3eefe394..15894e23 100644 --- a/apps/storefront/src/pages/address/components/AddressItemCard.tsx +++ b/apps/storefront/src/pages/address/components/AddressItemCard.tsx @@ -81,7 +81,7 @@ export const AddressItemCard = (props: OrderItemCardProps) => { }, } = useContext(GlobaledContext) - const hasPermission = !role || role === 3 + const hasPermission = !isB2BUser || !role || role === 3 return ( > + addressData?: AddressItemType + updateAddressList: (isFirst?: boolean) => void +} + +export const DeleteAddressDialog = (props: DeleteAddressDialogProps) => { + const { + isOpen, + setIsOpen, + addressData, + updateAddressList, + } = props + + const { + state: { + isB2BUser, + companyInfo: { + id: companyId, + }, + }, + } = useContext(GlobaledContext) + + const [isLoading, setIsLoading] = useState(false) + + const handleDelete = async () => { + if (!addressData) { + return + } + + try { + setIsLoading(true) + + const { + id = '', + } = addressData + + if (isB2BUser) { + await deleteB2BAddress({ + addressId: id, + companyId, + }) + } else { + // TODO BC接口 + } + + updateAddressList() + + setIsOpen(false) + } finally { + setIsLoading(false) + } + } + + return ( + { setIsOpen(false) }} + onConfirm={handleDelete} + isSpinning={isLoading} + > + + + Are you sure you want to delete this address? + + + + ) +} diff --git a/apps/storefront/src/pages/address/components/SetDefaultDialog.tsx b/apps/storefront/src/pages/address/components/SetDefaultDialog.tsx new file mode 100644 index 00000000..467f443b --- /dev/null +++ b/apps/storefront/src/pages/address/components/SetDefaultDialog.tsx @@ -0,0 +1,153 @@ +import { + ChangeEvent, + Dispatch, + SetStateAction, + useEffect, + useState, + useContext, +} from 'react' + +import { + Box, + FormGroup, + FormControlLabel, + Checkbox, +} from '@mui/material' + +import { + B3ConfirmDialog, +} from '@/components/B3ConfirmDialog' + +import { + GlobaledContext, +} from '@/shared/global' + +import { + updateB2BAddress, +} from '@/shared/service/b2b' + +import { + AddressItemType, +} from '../../../types/address' + +interface SetDefaultDialogProps { + isOpen: boolean + setIsOpen: Dispatch> + addressData?: AddressItemType + updateAddressList: (isFirst?: boolean) => void +} + +export const SetDefaultDialog = (props: SetDefaultDialogProps) => { + const { + isOpen, + setIsOpen, + addressData, + updateAddressList, + } = props + + const { + state: { + isB2BUser, + companyInfo: { + id: companyId, + }, + }, + } = useContext(GlobaledContext) + + const [isLoading, setIsLoading] = useState(false) + + const [address, setAddress] = useState() + + useEffect(() => { + setAddress(addressData) + }, [addressData]) + + const handleChange = (key: 'isDefaultShipping' | 'isDefaultBilling') => (e: ChangeEvent) => { + const { + checked, + } = e.target + + if (address) { + const newAddress = { + ...address, + } + if (key === 'isDefaultShipping') { + newAddress.isDefaultShipping = checked ? 1 : 0 + newAddress.isShipping = checked ? 1 : newAddress.isShipping + } + if (key === 'isDefaultBilling') { + newAddress.isDefaultBilling = checked ? 1 : 0 + newAddress.isBilling = checked ? 1 : newAddress.isShipping + } + setAddress(newAddress) + } + } + + const handleSetDefault = async () => { + try { + setIsLoading(true) + + if (isB2BUser) { + await updateB2BAddress({ + ...address, + companyId, + }) + } else { + // TODO BC接口 + } + + updateAddressList() + + setIsOpen(false) + } finally { + setIsLoading(false) + } + } + + return ( + { setIsOpen(false) }} + onConfirm={handleSetDefault} + isSpinning={isLoading} + > + { + address && ( + + + + )} + label="Set as default shipping address " + /> + + )} + label="Set as default billing address " + /> + + + ) + } + + ) +} diff --git a/apps/storefront/src/pages/address/shared/config.ts b/apps/storefront/src/pages/address/shared/config.ts index d8472efb..7f7c9330 100644 --- a/apps/storefront/src/pages/address/shared/config.ts +++ b/apps/storefront/src/pages/address/shared/config.ts @@ -30,14 +30,3 @@ export const filterFormConfig = [ size: 'small', }, ] - -export const filterSortConfig = { - isEnabled: false, - sortByList: [], - sortByLabel: '', -} - -export const filterPickerConfig = { - isEnabled: false, - label: '', -} diff --git a/apps/storefront/src/shared/service/b2b/graphql/address.ts b/apps/storefront/src/shared/service/b2b/graphql/address.ts index 298a8f47..4f527429 100644 --- a/apps/storefront/src/shared/service/b2b/graphql/address.ts +++ b/apps/storefront/src/shared/service/b2b/graphql/address.ts @@ -2,6 +2,10 @@ import { B3Request, } from '../../request/b3Fetch' +import { + convertArrayToGraphql, +} from '../../../../utils' + const getCustomerAddress = ({ companyId = 0, offset = 0, @@ -58,6 +62,52 @@ const getCustomerAddress = ({ } }` +const updateAddress = (data: CustomFieldItems) => `mutation{ + addressUpdate(addressData: { + companyId: ${data.companyId}, + firstName: "${data.firstName}", + lastName: "${data.lastName}", + addressLine1: "${data.addressLine1}", + addressLine2: "${data.addressLine2 || ''}", + country: "${data.country}", + countryCode: "${data.countryCode}", + state: "${data.state}", + stateCode: "${data.stateCode || ''}", + city: "${data.city}", + zipCode: "${data.zipCode}", + phoneNumber: "${data.phoneNumber}", + isShipping: ${data.isShipping}, + isBilling: ${data.isBilling}, + isDefaultShipping: ${data.isDefaultShipping}, + isDefaultBilling: ${data.isDefaultBilling}, + label: "${data.label}", + uuid: "${data.uuid}", + extraFields: ${convertArrayToGraphql(data.extraFields || [])}, + addressId: ${data.id} + }) { + address{ + id + } + } +}` + +const deleteAddress = (data: CustomFieldItems) => `mutation{ + addressDelete( + addressId: ${data.addressId}, + companyId: ${data.companyId}, + ) { + message + } +}` + export const getB2BCustomerAddress = (data: CustomFieldItems = {}): CustomFieldItems => B3Request.graphqlB2B({ query: getCustomerAddress(data), }) + +export const deleteB2BAddress = (data: CustomFieldItems = {}): CustomFieldItems => B3Request.graphqlB2B({ + query: deleteAddress(data), +}) + +export const updateB2BAddress = (data: CustomFieldItems = {}): CustomFieldItems => B3Request.graphqlB2B({ + query: updateAddress(data), +}) diff --git a/apps/storefront/src/shared/service/b2b/index.ts b/apps/storefront/src/shared/service/b2b/index.ts index 5eaac230..6a4e0ffd 100644 --- a/apps/storefront/src/shared/service/b2b/index.ts +++ b/apps/storefront/src/shared/service/b2b/index.ts @@ -62,7 +62,9 @@ import { } from './graphql/users' import { + deleteB2BAddress, getB2BCustomerAddress, + updateB2BAddress, } from './graphql/address' export { @@ -100,4 +102,6 @@ export { addOrUpdateUsers, deleteUsers, getB2BCustomerAddress, + deleteB2BAddress, + updateB2BAddress, }