fix: clean folder

This commit is contained in:
ferdiansyah783
2025-08-07 03:53:40 +07:00
parent 5f24ec7899
commit a72a64215a
208 changed files with 174 additions and 29968 deletions
@@ -1,37 +0,0 @@
// MUI Imports
import Button from '@mui/material/Button'
import Typography from '@mui/material/Typography'
import type { ButtonProps } from '@mui/material/Button'
// Type Imports
import type { ThemeColor } from '@core/types'
// Component Imports
import ConfirmationDialog from '@components/dialogs/confirmation-dialog'
import OpenDialogOnElementClick from '@components/dialogs/OpenDialogOnElementClick'
const CustomerDetailHeader = ({ customerId }: { customerId: string }) => {
// Vars
const buttonProps = (children: string, color: ThemeColor, variant: ButtonProps['variant']): ButtonProps => ({
children,
color,
variant
})
return (
<div className='flex flex-wrap justify-between max-sm:flex-col sm:items-center gap-x-6 gap-y-4'>
<div className='flex flex-col items-start gap-1'>
<Typography variant='h4'>{`Customer ID #${customerId}`}</Typography>
<Typography>Aug 17, 2020, 5:48 (ET)</Typography>
</div>
<OpenDialogOnElementClick
element={Button}
elementProps={buttonProps('Delete Customer', 'error', 'tonal')}
dialog={ConfirmationDialog}
dialogProps={{ type: 'delete-customer' }}
/>
</div>
)
}
export default CustomerDetailHeader
@@ -1,99 +0,0 @@
// MUI Imports
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
import Chip from '@mui/material/Chip'
import Divider from '@mui/material/Divider'
import Typography from '@mui/material/Typography'
import Button from '@mui/material/Button'
import type { ButtonProps } from '@mui/material/Button'
// Type Imports
import type { Customer } from '@/types/apps/ecommerceTypes'
// Component Imports
import CustomAvatar from '@core/components/mui/Avatar'
import EditUserInfo from '@components/dialogs/edit-user-info'
import OpenDialogOnElementClick from '@components/dialogs/OpenDialogOnElementClick'
const CustomerDetails = ({ customerData }: { customerData?: Customer }) => {
// Vars
const buttonProps: ButtonProps = {
variant: 'contained',
children: 'Edit Details'
}
return (
<Card>
<CardContent className='flex flex-col pbs-12 gap-6'>
<div className='flex flex-col justify-self-center items-center gap-6'>
<div className='flex flex-col items-center gap-4'>
<CustomAvatar src={customerData?.avatar} variant='rounded' alt='Customer Avatar' size={120} />
<div className='flex flex-col items-center text-center'>
<Typography variant='h5'>{customerData?.customer}</Typography>
<Typography>Customer ID #{customerData?.customerId}</Typography>
</div>
</div>
<div className='flex items-center justify-around gap-4 flex-wrap is-full'>
<div className='flex items-center gap-4'>
<CustomAvatar variant='rounded' skin='light' color='primary'>
<i className='tabler-shopping-cart' />
</CustomAvatar>
<div>
<Typography variant='h5'>{customerData?.order}</Typography>
<Typography>Orders</Typography>
</div>
</div>
<div className='flex items-center gap-4'>
<CustomAvatar variant='rounded' skin='light' color='primary'>
<i className='tabler-currency-dollar' />
</CustomAvatar>
<div>
<Typography variant='h5'>${customerData?.totalSpent}</Typography>
<Typography>Spent</Typography>
</div>
</div>
</div>
</div>
<div className='flex flex-col gap-4'>
<Typography variant='h5'>Details</Typography>
<Divider />
<div className='flex flex-col gap-2'>
<div className='flex items-center gap-1'>
<Typography color='text.primary' className='font-medium'>
Username:
</Typography>
<Typography>{customerData?.customer}</Typography>
</div>
<div className='flex items-center gap-1'>
<Typography color='text.primary' className='font-medium'>
Billing Email:
</Typography>
<Typography>{customerData?.email}</Typography>
</div>
<div className='flex items-center gap-1'>
<Typography color='text.primary' className='font-medium'>
Status:
</Typography>
<Chip label='Active' variant='tonal' color='success' size='small' />
</div>
<div className='flex items-center gap-1'>
<Typography color='text.primary' className='font-medium'>
Contact:
</Typography>
<Typography>+1 (234) 464-0600</Typography>
</div>
<div className='flex items-center gap-1'>
<Typography color='text.primary' className='font-medium'>
Country:
</Typography>
<Typography>{customerData?.country}</Typography>
</div>
</div>
</div>
<OpenDialogOnElementClick element={Button} elementProps={buttonProps} dialog={EditUserInfo} />
</CardContent>
</Card>
)
}
export default CustomerDetails
@@ -1,45 +0,0 @@
'use client'
// MUI Imports
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
import Typography from '@mui/material/Typography'
import MuiButton from '@mui/material/Button'
import { styled } from '@mui/material/styles'
import type { ButtonProps } from '@mui/material/Button'
// Component Imports
import UpgradePlan from '@components/dialogs/upgrade-plan'
import OpenDialogOnElementClick from '@components/dialogs/OpenDialogOnElementClick'
const Button = styled(MuiButton)<ButtonProps>(() => ({
backgroundColor: 'var(--mui-palette-common-white) !important',
color: 'var(--mui-palette-primary-main) !important'
}))
const CustomerPlan = () => {
// Vars
const buttonProps: ButtonProps = {
variant: 'contained',
children: 'Upgrade To Premium'
}
return (
<Card>
<CardContent className='flex flex-col gap-6 bg-gradient-to-tr from-primary to-[#9E95F5]'>
<div className='flex items-center justify-between'>
<div className='flex flex-col gap-4'>
<Typography variant='h5' color='common.white'>
Upgrade to premium
</Typography>
<Typography color='common.white'>Upgrade customer to premium membership to access pro features.</Typography>
</div>
<img src='/images/apps/ecommerce/3d-rocket.png' className='-mis-7 -mbe-7' />
</div>
<OpenDialogOnElementClick element={Button} elementProps={buttonProps} dialog={UpgradePlan} />
</CardContent>
</Card>
)
}
export default CustomerPlan
@@ -1,24 +0,0 @@
// MUI Imports
import Grid from '@mui/material/Grid2'
// Type Imports
import type { Customer } from '@/types/apps/ecommerceTypes'
// Component Imports
import CustomerDetails from './CustomerDetails'
import CustomerPlan from './CustomerPlan'
const CustomerLeftOverview = ({ customerData }: { customerData?: Customer }) => {
return (
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<CustomerDetails customerData={customerData} />
</Grid>
<Grid size={{ xs: 12 }}>
<CustomerPlan />
</Grid>
</Grid>
)
}
export default CustomerLeftOverview
@@ -1,177 +0,0 @@
// React Imports
import { useState } from 'react'
// MUI Imports
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
import CardHeader from '@mui/material/CardHeader'
import Chip from '@mui/material/Chip'
import Collapse from '@mui/material/Collapse'
import Divider from '@mui/material/Divider'
import Typography from '@mui/material/Typography'
import { useTheme } from '@mui/material/styles'
import IconButton from '@mui/material/IconButton'
import Button from '@mui/material/Button'
import type { ButtonProps } from '@mui/material/Button'
import type { IconButtonProps } from '@mui/material/IconButton'
// Component Imports
import OptionMenu from '@core/components/option-menu'
import AddNewAddress from '@components/dialogs/add-edit-address'
import OpenDialogOnElementClick from '@components/dialogs/OpenDialogOnElementClick'
type propsType = {
typeOfAddress: string
isDefaultAddress: boolean
name: string
streetAddress: string
area: string
city: string
}
const propData: propsType[] = [
{
typeOfAddress: 'Home',
isDefaultAddress: true,
name: 'Violet Mendoza',
streetAddress: '23 Shatinon Mekalan',
area: 'Melbourne, VIC 3000,',
city: 'London'
},
{
typeOfAddress: 'Office',
isDefaultAddress: false,
name: 'Archie Mendoza',
streetAddress: '45 Roker Terrace',
area: 'Latheronwheel',
city: 'London'
},
{
typeOfAddress: 'Family',
isDefaultAddress: false,
name: 'George Mendoza',
streetAddress: '512 Water Plant',
area: 'Melbourne, VIC 3000',
city: 'London'
}
]
// Vars
const data = {
firstName: 'Violet',
lastName: 'Mendoza',
email: 'sbaser0@boston.com',
country: 'UK',
address1: '23 Shatinon Mekalan',
address2: 'Melbourne, VIC 3000',
landmark: 'Near Water Plant',
city: 'London',
state: 'Capholim',
zipCode: '403114',
taxId: 'TAX-875623',
vatNumber: 'SDF754K77',
contact: '+1 (234) 464-0600'
}
const CustomerAddress = (props: propsType) => {
// Props
const { typeOfAddress, isDefaultAddress, name, streetAddress, area, city } = props
// States
const [expanded, setExpanded] = useState(isDefaultAddress ? true : false)
// Vars
const iconButtonProps: IconButtonProps = {
children: <i className='tabler-edit' />,
className: 'text-textSecondary'
}
// Hooks
const theme = useTheme()
return (
<>
<div className='flex flex-wrap justify-between items-center mlb-3 gap-y-2'>
<div className='flex items-center gap-2'>
<IconButton
size='large'
sx={{
'& i': {
transition: 'transform 0.3s',
transform: expanded ? 'rotate(0deg)' : theme.direction === 'ltr' ? 'rotate(-90deg)' : 'rotate(90deg)'
}
}}
onClick={() => setExpanded(!expanded)}
>
<i className='tabler-chevron-down text-textPrimary' />
</IconButton>
<div className='flex flex-col items-start gap-1'>
<div className='flex items-center gap-2'>
<Typography color='text.primary' className='font-medium'>
{typeOfAddress}
</Typography>
{isDefaultAddress && <Chip variant='tonal' color='success' label='Default Address' size='small' />}
</div>
<Typography>{streetAddress}</Typography>
</div>
</div>
<div className='mis-10'>
<OpenDialogOnElementClick
element={IconButton}
elementProps={iconButtonProps}
dialog={AddNewAddress}
dialogProps={{ data }}
/>
<IconButton>
<i className='tabler-trash text-textSecondary' />
</IconButton>
<OptionMenu
iconClassName='text-textSecondary'
iconButtonProps={{ size: 'medium' }}
options={['Set as Default Address']}
/>
</div>
</div>
<Collapse in={expanded} timeout={300}>
<div className='flex flex-col gap-1 pb-3 pis-14'>
<Typography color='text.primary' className='font-medium'>
{name}
</Typography>
<div>
<Typography>{streetAddress}</Typography>
<Typography>{area}</Typography>
<Typography>{city}</Typography>
</div>
</div>
</Collapse>
</>
)
}
const AddressBook = () => {
// Vars
const buttonProps: ButtonProps = {
variant: 'tonal',
children: 'Add New Address',
size: 'small'
}
return (
<Card>
<CardHeader
title='Address Book'
action={<OpenDialogOnElementClick element={Button} elementProps={buttonProps} dialog={AddNewAddress} />}
/>
<CardContent>
{propData.map((address, index) => (
<div key={index}>
<CustomerAddress {...address} />
{index !== propData.length - 1 && <Divider />}
</div>
))}
</CardContent>
</Card>
)
}
export default AddressBook
@@ -1,242 +0,0 @@
// React Imports
import { useState } from 'react'
// MUI Imports
import Grid from '@mui/material/Grid2'
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import Collapse from '@mui/material/Collapse'
import Chip from '@mui/material/Chip'
import Divider from '@mui/material/Divider'
import Typography from '@mui/material/Typography'
import { useTheme } from '@mui/material/styles'
import IconButton from '@mui/material/IconButton'
import Button from '@mui/material/Button'
import type { ButtonProps } from '@mui/material/Button'
import type { IconButtonProps } from '@mui/material/IconButton'
// Component Imports
import CustomAvatar from '@core/components/mui/Avatar'
import OptionMenu from '@core/components/option-menu'
import AddNewCard from '@components/dialogs/billing-card'
import OpenDialogOnElementClick from '@components/dialogs/OpenDialogOnElementClick'
type dataType = {
typeOfCard: string
isDefaultCard: boolean
expiryDate: string
}
const data: dataType[] = [
{
typeOfCard: 'Mastercard',
isDefaultCard: true,
expiryDate: 'Apr 2028'
},
{
typeOfCard: 'American Express',
isDefaultCard: false,
expiryDate: 'Jan 2025'
},
{
typeOfCard: 'Visa',
isDefaultCard: false,
expiryDate: 'Nov 2030'
}
]
// Vars
const editCardData = {
cardNumber: '**** **** **** 4487',
name: 'Violet Mendoza ',
expiryDate: '04/2028',
cardCvv: '233'
}
const CustomerAddress = (props: dataType) => {
// Props
const { typeOfCard, isDefaultCard, expiryDate } = props
// States
const [expanded, setExpanded] = useState(isDefaultCard ? true : false)
// Vars
const iconButtonProps: IconButtonProps = {
children: <i className='tabler-edit' />,
className: 'text-textSecondary'
}
// Hooks
const theme = useTheme()
const mastercard = '/images/apps/ecommerce/mastercard.png'
const americanExpress = '/images/apps/ecommerce/american-express.png'
const visa = '/images/apps/ecommerce/visa.png'
return (
<>
<div className='flex flex-wrap justify-between items-center mlb-3 gap-y-2'>
<div className='flex items-center gap-2'>
<IconButton
size='large'
sx={{
'& i': {
transition: 'transform 0.3s',
transform: expanded ? 'rotate(0deg)' : theme.direction === 'ltr' ? 'rotate(-90deg)' : 'rotate(90deg)'
}
}}
onClick={() => setExpanded(!expanded)}
>
<i className='tabler-chevron-down text-textPrimary' />
</IconButton>
<div className='flex items-center gap-4'>
<div className='flex justify-center items-center bg-[#F6F8FA] rounded-sm is-[50px] bs-[30px]'>
<img
src={
typeOfCard === 'Mastercard' ? mastercard : typeOfCard === 'American Express' ? americanExpress : visa
}
alt={typeOfCard}
height={typeOfCard === 'Mastercard' ? 19 : typeOfCard === 'American Express' ? 16 : 12}
/>
</div>
<div className='flex flex-col items-start gap-1'>
<div className='flex flex-wrap items-center gap-x-2 gap-y-1'>
<Typography color='text.primary' className='font-medium'>
{typeOfCard}
</Typography>
{isDefaultCard && <Chip variant='tonal' color='success' label='Default Card' size='small' />}
</div>
<Typography>Expires {expiryDate}</Typography>
</div>
</div>
</div>
<div className='mis-10'>
<OpenDialogOnElementClick
element={IconButton}
elementProps={iconButtonProps}
dialog={AddNewCard}
dialogProps={{ data: editCardData }}
/>
<IconButton>
<i className='tabler-trash text-textSecondary' />
</IconButton>
<OptionMenu
iconClassName='text-textSecondary'
iconButtonProps={{ size: 'medium' }}
options={['Set as Default Card']}
/>
</div>
</div>
<Collapse in={expanded} timeout={300}>
<Grid container spacing={6} className='pbe-3 pis-12'>
<Grid size={{ xs: 12, md: 6 }}>
<Grid container spacing={2}>
<Grid size={{ xs: 4 }}>
<div className='flex flex-col gap-1'>
<Typography variant='body2'>Name</Typography>
<Typography variant='body2'>Number</Typography>
<Typography variant='body2'>Expires</Typography>
<Typography variant='body2'>Type</Typography>
<Typography variant='body2'>Issuer</Typography>
<Typography variant='body2'>ID</Typography>
</div>
</Grid>
<Grid size={{ xs: 8 }}>
<div className='flex flex-col gap-1'>
<Typography variant='body2' color='text.primary' className='font-medium'>
Violet Mendoza
</Typography>
<Typography variant='body2' color='text.primary' className='font-medium'>
**** 4487
</Typography>
<Typography variant='body2' color='text.primary' className='font-medium'>
08/2028
</Typography>
<Typography variant='body2' color='text.primary' className='font-medium'>
{typeOfCard}
</Typography>
<Typography variant='body2' color='text.primary' className='font-medium'>
VICBANK
</Typography>
<Typography variant='body2' color='text.primary' className='font-medium'>
DH73DJ8
</Typography>
</div>
</Grid>
</Grid>
</Grid>
<Grid size={{ xs: 12, md: 6 }}>
<Grid container>
<Grid size={{ xs: 4 }}>
<div className='flex flex-col gap-1'>
<Typography variant='body2'>Billing</Typography>
<Typography variant='body2'>Number</Typography>
<Typography variant='body2'>Email</Typography>
<Typography variant='body2'>Origin</Typography>
<Typography variant='body2'>CVC</Typography>
</div>
</Grid>
<Grid size={{ xs: 8 }}>
<div className='flex flex-col gap-1'>
<Typography variant='body2' color='text.primary' className='font-medium'>
USA
</Typography>
<Typography variant='body2' color='text.primary' className='font-medium'>
+7634 983 637
</Typography>
<Typography variant='body2' color='text.primary' className='font-medium'>
vafgot@vultukir.org
</Typography>
<div className='flex gap-2'>
<Typography variant='body2' color='text.primary' className='font-medium'>
United States
</Typography>
<img src='/images/cards/us.png' height={20} />
</div>
<div className='flex gap-2'>
<Typography variant='body2' color='text.primary' className='font-medium'>
Passed
</Typography>
<CustomAvatar skin='light' size={20} color='success'>
<i className='tabler-check text-xs' />
</CustomAvatar>
</div>
</div>
</Grid>
</Grid>
</Grid>
</Grid>
</Collapse>
</>
)
}
const PaymentMethod = () => {
// Vars
const buttonProps: ButtonProps = {
variant: 'tonal',
children: 'New Payment Methods',
size: 'small'
}
return (
<Card>
<CardHeader
title='Payment Methods'
action={<OpenDialogOnElementClick element={Button} elementProps={buttonProps} dialog={AddNewCard} />}
className='flex-wrap gap-4'
/>
<CardContent>
{data.map((address, index) => (
<div key={index}>
<CustomerAddress {...address} />
{index !== data.length - 1 && <Divider />}
</div>
))}
</CardContent>
</Card>
)
}
export default PaymentMethod
@@ -1,23 +0,0 @@
'use client'
// MUI Imports
import Grid from '@mui/material/Grid2'
// Component Imports
import AddressBook from './AddressBookCard'
import PaymentMethod from './PaymentMethodCard'
const AddressBilling = () => {
return (
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<AddressBook />
</Grid>
<Grid size={{ xs: 12 }}>
<PaymentMethod />
</Grid>
</Grid>
)
}
export default AddressBilling
@@ -1,57 +0,0 @@
'use client'
// React Imports
import { useState } from 'react'
import type { SyntheticEvent, ReactElement } from 'react'
// MUI Imports
import Tab from '@mui/material/Tab'
import TabContext from '@mui/lab/TabContext'
import TabPanel from '@mui/lab/TabPanel'
import Grid from '@mui/material/Grid2'
// Component Imports
import CustomTabList from '@core/components/mui/TabList'
const CustomerRight = ({ tabContentList }: { tabContentList: { [key: string]: ReactElement } }) => {
// States
const [activeTab, setActiveTab] = useState('overview')
const handleChange = (event: SyntheticEvent, value: string) => {
setActiveTab(value)
}
return (
<>
<TabContext value={activeTab}>
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<CustomTabList onChange={handleChange} variant='scrollable' pill='true'>
<Tab icon={<i className='tabler-user' />} value='overview' label='Overview' iconPosition='start' />
<Tab icon={<i className='tabler-lock' />} value='security' label='Security' iconPosition='start' />
<Tab
icon={<i className='tabler-map-pin' />}
value='addressBilling'
label='Address & Billing'
iconPosition='start'
/>
<Tab
icon={<i className='tabler-bell' />}
value='notifications'
label='Notifications'
iconPosition='start'
/>
</CustomTabList>
</Grid>
<Grid size={{ xs: 12 }}>
<TabPanel value={activeTab} className='p-0'>
{tabContentList[activeTab]}
</TabPanel>
</Grid>
</Grid>
</TabContext>
</>
)
}
export default CustomerRight
@@ -1,93 +0,0 @@
// MUI Imports
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import CardActions from '@mui/material/CardActions'
import Typography from '@mui/material/Typography'
import Checkbox from '@mui/material/Checkbox'
import Button from '@mui/material/Button'
// Style Imports
import tableStyles from '@core/styles/table.module.css'
type TableDataType = {
type: string
app: boolean
email: boolean
browser: boolean
}
// Vars
const tableData: TableDataType[] = [
{
app: false,
email: true,
browser: false,
type: 'New for you'
},
{
app: true,
email: false,
browser: true,
type: 'Account activity'
},
{
app: true,
email: true,
browser: true,
type: 'A new browser used to sign in'
},
{
app: false,
email: false,
browser: true,
type: 'A new device is linked'
}
]
const Notification = () => {
return (
<Card>
<CardHeader title='Notifications' subheader='You will receive notification for the below selected items' />
<div className='overflow-x-auto'>
<table className={tableStyles.table}>
<thead>
<tr>
<th>Type</th>
<th>Email</th>
<th>Browser</th>
<th>App</th>
</tr>
</thead>
<tbody className='border-be'>
{tableData.map((data, index) => (
<tr key={index}>
<td>
<Typography color='text.primary'>{data.type}</Typography>
</td>
<td>
<Checkbox defaultChecked={data.email} />
</td>
<td>
<Checkbox defaultChecked={data.browser} />
</td>
<td>
<Checkbox defaultChecked={data.app} />
</td>
</tr>
))}
</tbody>
</table>
</div>
<CardActions className='flex items-center'>
<Button variant='contained' type='submit'>
Save Changes
</Button>
<Button variant='tonal' color='secondary' type='reset'>
Discard
</Button>
</CardActions>
</Card>
)
}
export default Notification
@@ -1,22 +0,0 @@
// MUI Imports
import Grid from '@mui/material/Grid2'
// Types Imports
import type { CardStatsCustomerStatsProps } from '@/types/pages/widgetTypes'
// Component Imports
import CustomerStats from '@components/card-statistics/CustomerStats'
const CustomerStatisticsCard = ({ customerStatData }: { customerStatData?: CardStatsCustomerStatsProps[] }) => {
return (
<Grid container spacing={6}>
{customerStatData?.map((item, index) => (
<Grid size={{ xs: 12, md: 6 }} key={index}>
<CustomerStats {...item} />
</Grid>
))}
</Grid>
)
}
export default CustomerStatisticsCard
@@ -1,312 +0,0 @@
'use client'
// React Imports
import { useEffect, useMemo, useState } from 'react'
// Next Imports
import Link from 'next/link'
import { useParams } from 'next/navigation'
// MUI Imports
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
import Chip from '@mui/material/Chip'
import type { TextFieldProps } from '@mui/material/TextField'
import Typography from '@mui/material/Typography'
// Third-party Imports
import type { RankingInfo } from '@tanstack/match-sorter-utils'
import { rankItem } from '@tanstack/match-sorter-utils'
import type { ColumnDef, FilterFn } from '@tanstack/react-table'
import {
createColumnHelper,
flexRender,
getCoreRowModel,
getFacetedMinMaxValues,
getFacetedRowModel,
getFacetedUniqueValues,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable
} from '@tanstack/react-table'
import classnames from 'classnames'
// Type Imports
import type { OrderType } from '@/types/apps/ecommerceTypes'
import type { Locale } from '@configs/i18n'
import type { ThemeColor } from '@core/types'
// Component Imports
import CustomTextField from '@core/components/mui/TextField'
import OptionMenu from '@core/components/option-menu'
// Util Imports
import { getLocalizedUrl } from '@/utils/i18n'
// Style Imports
import tableStyles from '@core/styles/table.module.css'
declare module '@tanstack/table-core' {
interface FilterFns {
fuzzy: FilterFn<unknown>
}
interface FilterMeta {
itemRank: RankingInfo
}
}
type PayementStatusType = {
text: string
color: ThemeColor
}
type StatusChipColorType = {
color: ThemeColor
}
export const paymentStatus: { [key: number]: PayementStatusType } = {
1: { text: 'Paid', color: 'success' },
2: { text: 'Pending', color: 'warning' },
3: { text: 'Cancelled', color: 'secondary' },
4: { text: 'Failed', color: 'error' }
}
export const statusChipColor: { [key: string]: StatusChipColorType } = {
Delivered: { color: 'success' },
'Out for Delivery': { color: 'primary' },
'Ready to Pickup': { color: 'info' },
Dispatched: { color: 'warning' }
}
type ECommerceOrderTypeWithAction = OrderType & {
action?: string
}
const fuzzyFilter: FilterFn<any> = (row, columnId, value, addMeta) => {
// Rank the item
const itemRank = rankItem(row.getValue(columnId), value)
// Store the itemRank info
addMeta({
itemRank
})
// Return if the item should be filtered in/out
return itemRank.passed
}
const DebouncedInput = ({
value: initialValue,
onChange,
debounce = 500,
...props
}: {
value: string | number
onChange: (value: string | number) => void
debounce?: number
} & Omit<TextFieldProps, 'onChange'>) => {
// States
const [value, setValue] = useState(initialValue)
useEffect(() => {
setValue(initialValue)
}, [initialValue])
useEffect(() => {
const timeout = setTimeout(() => {
onChange(value)
}, debounce)
return () => clearTimeout(timeout)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [value])
return <CustomTextField {...props} value={value} onChange={e => setValue(e.target.value)} />
}
// Column Definitions
const columnHelper = createColumnHelper<ECommerceOrderTypeWithAction>()
const OrderListTable = ({ orderData }: { orderData?: OrderType[] }) => {
// States
const [rowSelection, setRowSelection] = useState({})
const [data, setData] = useState(...[orderData])
const [globalFilter, setGlobalFilter] = useState('')
// Hooks
const { lang: locale } = useParams()
const columns = useMemo<ColumnDef<ECommerceOrderTypeWithAction, any>[]>(
() => [
columnHelper.accessor('order', {
header: 'order',
cell: ({ row }) => (
<Typography
component={Link}
href={getLocalizedUrl(`/apps/ecommerce/orders/details/${row.original.order}`, locale as Locale)}
color='primary.main'
>{`#${row.original.order}`}</Typography>
)
}),
columnHelper.accessor('date', {
header: 'Date',
cell: ({ row }) => <Typography>{`${new Date(row.original.date).toDateString()}`}</Typography>
}),
columnHelper.accessor('status', {
header: 'Status',
cell: ({ row }) => (
<Chip
label={row.original.status}
color={statusChipColor[row.original.status].color}
variant='tonal'
size='small'
/>
)
}),
columnHelper.accessor('spent', {
header: 'Spent',
cell: ({ row }) => <Typography>${row.original.spent}</Typography>
}),
columnHelper.accessor('action', {
header: 'Actions',
cell: ({ row }) => (
<div className='flex items-center'>
<OptionMenu
iconButtonProps={{ size: 'medium' }}
iconClassName='text-textSecondary text-[22px]'
options={[
{
text: 'View',
icon: 'tabler-eye',
href: getLocalizedUrl(`/apps/ecommerce/orders/details/${row.original.order}`, locale as Locale),
linkProps: { className: 'flex items-center is-full plb-1.5 pli-4' }
},
{
text: 'Delete',
icon: 'tabler-trash text-[22px]',
menuItemProps: {
onClick: () => setData(data?.filter(order => order.id !== row.original.id)),
className: 'flex items-center'
}
}
]}
/>
</div>
),
enableSorting: false
})
],
// eslint-disable-next-line react-hooks/exhaustive-deps
[data]
)
const table = useReactTable({
data: data as OrderType[],
columns,
filterFns: {
fuzzy: fuzzyFilter
},
state: {
rowSelection,
globalFilter
},
initialState: {
pagination: {
pageSize: 6
}
},
enableRowSelection: true, //enable row selection for all rows
// enableRowSelection: row => row.original.age > 18, // or enable row selection conditionally per row
globalFilterFn: fuzzyFilter,
onRowSelectionChange: setRowSelection,
getCoreRowModel: getCoreRowModel(),
onGlobalFilterChange: setGlobalFilter,
getFilteredRowModel: getFilteredRowModel(),
getSortedRowModel: getSortedRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getFacetedRowModel: getFacetedRowModel(),
getFacetedUniqueValues: getFacetedUniqueValues(),
getFacetedMinMaxValues: getFacetedMinMaxValues()
})
return (
<Card>
<CardContent className='flex justify-between flex-col items-start sm:flex-row sm:items-center gap-y-4'>
<Typography variant='h5'>Orders Placed</Typography>
<DebouncedInput
value={globalFilter ?? ''}
onChange={value => setGlobalFilter(String(value))}
placeholder='Search Order'
className='max-sm:is-full'
/>
</CardContent>
<div className='overflow-x-auto'>
<table className={tableStyles.table}>
<thead>
{table.getHeaderGroups().map(headerGroup => (
<tr key={headerGroup.id}>
{headerGroup.headers.map(header => (
<th key={header.id}>
{header.isPlaceholder ? null : (
<>
<div
className={classnames({
'flex items-center': header.column.getIsSorted(),
'cursor-pointer select-none': header.column.getCanSort()
})}
onClick={header.column.getToggleSortingHandler()}
>
{flexRender(header.column.columnDef.header, header.getContext())}
{{
asc: <i className='tabler-chevron-up text-xl' />,
desc: <i className='tabler-chevron-down text-xl' />
}[header.column.getIsSorted() as 'asc' | 'desc'] ?? null}
</div>
</>
)}
</th>
))}
</tr>
))}
</thead>
{table.getFilteredRowModel().rows.length === 0 ? (
<tbody>
<tr>
<td colSpan={table.getVisibleFlatColumns().length} className='text-center'>
No data available
</td>
</tr>
</tbody>
) : (
<tbody>
{table
.getRowModel()
.rows.slice(0, table.getState().pagination.pageSize)
.map(row => {
return (
<tr key={row.id} className={classnames({ selected: row.getIsSelected() })}>
{row.getVisibleCells().map(cell => (
<td key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</td>
))}
</tr>
)
})}
</tbody>
)}
</table>
</div>
{/* <TablePagination
component={() => <TablePaginationComponent table={table} />}
count={table.getFilteredRowModel().rows.length}
rowsPerPage={table.getState().pagination.pageSize}
page={table.getState().pagination.pageIndex}
onPageChange={(_, page) => {
table.setPageIndex(page)
}}
/> */}
</Card>
)
}
export default OrderListTable
@@ -1,64 +0,0 @@
// MUI Imports
import Grid from '@mui/material/Grid2'
// Component Imports
import CustomerStatisticsCard from './CustomerStatisticsCard'
import OrderListTable from './OrderListTable'
// Data Imports
import { getStatisticsData, getEcommerceData } from '@/app/server/actions'
/**
* ! If you need data using an API call, uncomment the below API code, update the `process.env.API_URL` variable in the
* ! `.env` file found at root of your project and also update the API endpoints like `/pages/widget-examples` in below example.
* ! Also, remove the above server action import and the action itself from the `src/app/server/actions.ts` file to clean up unused code
* ! because we've used the server action for getting our static data.
*/
/* const getStatisticsData = async () => {
// Vars
const res = await fetch(`${process.env.API_URL}/pages/widget-examples`)
if (!res.ok) {
throw new Error('Failed to fetch statistics data')
}
return res.json()
} */
/**
* ! If you need data using an API call, uncomment the below API code, update the `process.env.API_URL` variable in the
* ! `.env` file found at root of your project and also update the API endpoints like `/apps/ecommerce` in below example.
* ! Also, remove the above server action import and the action itself from the `src/app/server/actions.ts` file to clean up unused code
* ! because we've used the server action for getting our static data.
*/
/* const getEcommerceData = async () => {
// Vars
const res = await fetch(`${process.env.API_URL}/apps/ecommerce`)
if (!res.ok) {
throw new Error('Failed to fetch ecommerce data')
}
return res.json()
} */
const Overview = async () => {
// Vars
const data = await getStatisticsData()
const tableData = await getEcommerceData()
return (
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<CustomerStatisticsCard customerStatData={data?.customerStats} />
</Grid>
<Grid size={{ xs: 12 }}>
<OrderListTable orderData={tableData?.orderData} />
</Grid>
</Grid>
)
}
export default Overview
@@ -1,95 +0,0 @@
'use client'
// React Imports
import { useState } from 'react'
// MUI Imports
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import Grid from '@mui/material/Grid2'
import InputAdornment from '@mui/material/InputAdornment'
import IconButton from '@mui/material/IconButton'
import Alert from '@mui/material/Alert'
import AlertTitle from '@mui/material/AlertTitle'
import Button from '@mui/material/Button'
// Component Imports
import CustomTextField from '@core/components/mui/TextField'
const ChangePassword = () => {
// States
const [isPasswordShown, setIsPasswordShown] = useState(false)
const [isConfirmPasswordShown, setIsConfirmPasswordShown] = useState(false)
return (
<Card>
<CardHeader title='Change Password' />
<CardContent className='flex flex-col gap-4'>
<Alert icon={false} severity='warning' onClose={() => {}}>
<AlertTitle>Ensure that these requirements are met</AlertTitle>
Minimum 8 characters long, uppercase & symbol
</Alert>
<form>
<Grid container spacing={4}>
<Grid size={{ xs: 12 }}>
<Grid container spacing={6}>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='Password'
type={isPasswordShown ? 'text' : 'password'}
placeholder='············'
slotProps={{
input: {
endAdornment: (
<InputAdornment position='end'>
<IconButton
edge='end'
onClick={() => setIsPasswordShown(!isPasswordShown)}
onMouseDown={e => e.preventDefault()}
>
<i className={isPasswordShown ? 'tabler-eye-off' : 'tabler-eye'} />
</IconButton>
</InputAdornment>
)
}
}}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='Confirm Password'
type={isConfirmPasswordShown ? 'text' : 'password'}
placeholder='············'
slotProps={{
input: {
endAdornment: (
<InputAdornment position='end'>
<IconButton
edge='end'
onClick={() => setIsConfirmPasswordShown(!isConfirmPasswordShown)}
onMouseDown={e => e.preventDefault()}
>
<i className={isConfirmPasswordShown ? 'tabler-eye-off' : 'tabler-eye'} />
</IconButton>
</InputAdornment>
)
}
}}
/>
</Grid>
</Grid>
</Grid>
<Grid size={{ xs: 12 }}>
<Button variant='contained'>Change Password</Button>
</Grid>
</Grid>
</form>
</CardContent>
</Card>
)
}
export default ChangePassword
@@ -1,93 +0,0 @@
// React Imports
import type { ReactElement } from 'react'
// MUI Imports
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import Typography from '@mui/material/Typography'
// Style Imports
import tableStyles from '@core/styles/table.module.css'
type DataType = {
device: string
browser: string
location: string
recentActivity: string
browserIcon: ReactElement
}
// Vars
const recentDeviceData: DataType[] = [
{
device: 'Dell XPS 15',
location: 'United States',
browser: 'Chrome on Windows',
recentActivity: '10, Jan 2020 20:07',
browserIcon: <i className='tabler-brand-windows text-[22px] text-info' />
},
{
location: 'Ghana',
device: 'Google Pixel 3a',
browser: 'Chrome on Android',
recentActivity: '11, Jan 2020 10:16',
browserIcon: <i className='tabler-brand-android text-[22px] text-success' />
},
{
location: 'Mayotte',
device: 'Apple iMac',
browser: 'Chrome on MacOS',
recentActivity: '11, Jan 2020 12:10',
browserIcon: <i className='tabler-brand-apple text-[22px] text-secondary' />
},
{
location: 'Mauritania',
device: 'Apple iPhone XR',
browser: 'Chrome on iPhone',
recentActivity: '12, Jan 2020 8:29',
browserIcon: <i className='tabler-device-mobile text-[22px] text-error' />
}
]
const RecentDevice = () => {
return (
<Card>
<CardHeader title='Recent Devices' />
<div className='overflow-x-auto'>
<table className={tableStyles.table}>
<thead>
<tr>
<th>Browser</th>
<th>Device</th>
<th>Location</th>
<th>Recent Activities</th>
</tr>
</thead>
<tbody>
{recentDeviceData.map((device, index) => (
<tr key={index}>
<td>
<div className='flex items-center gap-4'>
{device.browserIcon}
<Typography color='text.primary'>{device.browser}</Typography>
</div>
</td>
<td>
<Typography>{device.device}</Typography>
</td>
<td>
<Typography>{device.location}</Typography>
</td>
<td>
<Typography>{device.recentActivity}</Typography>
</td>
</tr>
))}
</tbody>
</table>
</div>
</Card>
)
}
export default RecentDevice
@@ -1,44 +0,0 @@
// MUI Imports
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import InputLabel from '@mui/material/InputLabel'
import Typography from '@mui/material/Typography'
// Component Imports
import Link from '@components/Link'
import CustomIconButton from '@core/components/mui/IconButton'
import CustomTextField from '@core/components/mui/TextField'
const TwoStepVerification = () => {
return (
<Card>
<CardHeader title='Two-step verification' subheader='Keep your account secure with authentication step.' />
<CardContent>
<InputLabel htmlFor='sms' className='font-medium text-textPrimary mbe-1'>
SMS
</InputLabel>
<div className='flex items-center gap-4 mbe-4'>
<CustomTextField id='sms' placeholder='+1(968) 819-2547' fullWidth />
<div className='flex'>
<CustomIconButton>
<i className='tabler-edit text-textPrimary' />
</CustomIconButton>
<CustomIconButton>
<i className='tabler-user-plus text-textPrimary' />
</CustomIconButton>
</div>
</div>
<Typography>
Two-factor authentication adds an additional layer of security to your account by requiring more than just a
password to log in.{' '}
<Typography component={Link} color='primary.main'>
Learn more.
</Typography>
</Typography>
</CardContent>
</Card>
)
}
export default TwoStepVerification
@@ -1,25 +0,0 @@
// MUI Imports
import Grid from '@mui/material/Grid2'
// Component Imports
import ChangePassword from './ChangePassword'
import TwoStepVerification from './TwoStepVerification'
import RecentDevice from './RecentDevice'
const SecurityTab = () => {
return (
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<ChangePassword />
</Grid>
<Grid size={{ xs: 12 }}>
<TwoStepVerification />
</Grid>
<Grid size={{ xs: 12 }}>
<RecentDevice />
</Grid>
</Grid>
)
}
export default SecurityTab
@@ -1,50 +0,0 @@
// React Imports
import type { ReactElement } from 'react'
// Next Imports
import dynamic from 'next/dynamic'
// MUI Imports
import Grid from '@mui/material/Grid2'
// Type Imports
import type { Customer } from '@/types/apps/ecommerceTypes'
// Component Imports
import CustomerDetailsHeader from './CustomerDetailsHeader'
import CustomerLeftOverview from './customer-left-overview'
import CustomerRight from './customer-right'
const OverViewTab = dynamic(() => import('@views/apps/ecommerce/customers/details/customer-right/overview'))
const SecurityTab = dynamic(() => import('@views/apps/ecommerce/customers/details/customer-right/security'))
const NotificationsTab = dynamic(() => import('@views/apps/ecommerce/customers/details/customer-right/notification'))
const AddressBillingTab = dynamic(
() => import('@views/apps/ecommerce/customers/details/customer-right/address-billing')
)
// Vars
const tabContentList = (): { [key: string]: ReactElement } => ({
overview: <OverViewTab />,
security: <SecurityTab />,
addressBilling: <AddressBillingTab />,
notifications: <NotificationsTab />
})
const CustomerDetails = ({ customerData, customerId }: { customerData?: Customer; customerId: string }) => {
return (
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<CustomerDetailsHeader customerId={customerId} />
</Grid>
<Grid size={{ xs: 12, md: 4 }}>
<CustomerLeftOverview customerData={customerData} />
</Grid>
<Grid size={{ xs: 12, md: 8 }}>
<CustomerRight tabContentList={tabContentList()} />
</Grid>
</Grid>
)
}
export default CustomerDetails