initial commit

This commit is contained in:
ferdiansyah783
2025-08-05 12:35:40 +07:00
commit fffa2ead5c
1069 changed files with 118056 additions and 0 deletions
@@ -0,0 +1,30 @@
'use client'
//Mui Imports
import { styled } from '@mui/material'
import Button from '@mui/material/Button'
import type { ButtonProps } from '@mui/material/Button'
const DialogCloseButton = styled(Button)<ButtonProps>({
top: 0,
right: 0,
color: 'var(--mui-palette-text-disabled)',
position: 'absolute',
boxShadow: 'var(--mui-customShadows-xs)',
transform: 'translate(9px, -10px)',
borderRadius: 'var(--mui-shape-customBorderRadius-sm)',
backgroundColor: 'var(--mui-palette-background-paper) !important',
transition: 'transform 0.25s ease-in-out, box-shadow 0.25s ease-in-out',
blockSize: 30,
inlineSize: 30,
minInlineSize: 0,
padding: 0,
'&:hover, &:active': {
transform: 'translate(7px, -5px) !important'
},
'& i, & svg': {
fontSize: '1.25rem'
}
})
export default DialogCloseButton
@@ -0,0 +1,40 @@
'use client'
// React Imports
import { useState } from 'react'
import type { ComponentType } from 'react'
type OpenDialogOnElementClickProps = {
element: ComponentType<any>
dialog: ComponentType<any>
elementProps?: any
dialogProps?: any
}
const OpenDialogOnElementClick = (props: OpenDialogOnElementClickProps) => {
// Props
const { element: Element, dialog: Dialog, elementProps, dialogProps } = props
// States
const [open, setOpen] = useState(false)
// Extract onClick from elementProps
const { onClick: elementOnClick, ...restElementProps } = elementProps
// Handle onClick event
const handleOnClick = (e: MouseEvent) => {
elementOnClick && elementOnClick(e)
setOpen(true)
}
return (
<>
{/* Receive element component as prop and we will pass onclick event which changes state to open */}
<Element onClick={handleOnClick} {...restElementProps} />
{/* Receive dialog component as prop and we will pass open and setOpen props to that component */}
<Dialog open={open} setOpen={setOpen} {...dialogProps} closeAfterTransition={false} />
</>
)
}
export default OpenDialogOnElementClick
@@ -0,0 +1,275 @@
'use client'
// React Imports
import { useEffect, useState } from 'react'
import type { ChangeEvent } from 'react'
// MUI Imports
import Dialog from '@mui/material/Dialog'
import DialogTitle from '@mui/material/DialogTitle'
import DialogContent from '@mui/material/DialogContent'
import DialogActions from '@mui/material/DialogActions'
import Button from '@mui/material/Button'
import Typography from '@mui/material/Typography'
import Grid from '@mui/material/Grid2'
import MenuItem from '@mui/material/MenuItem'
import Switch from '@mui/material/Switch'
import FormControlLabel from '@mui/material/FormControlLabel'
// Third-party Imports
import classnames from 'classnames'
// Type Import
import type { CustomInputVerticalData } from '@core/components/custom-inputs/types'
// Component Imports
import CustomInputVertical from '@core/components/custom-inputs/Vertical'
import DialogCloseButton from '../DialogCloseButton'
import CustomTextField from '@core/components/mui/TextField'
type AddEditAddressData = {
firstName?: string
lastName?: string
country?: string
address1?: string
address2?: string
landmark?: string
city?: string
state?: string
zipCode?: string
}
type AddEditAddressProps = {
open: boolean
setOpen: (open: boolean) => void
data?: AddEditAddressData
}
const countries = ['Select Country', 'France', 'Russia', 'China', 'UK', 'US']
const initialAddressData: AddEditAddressProps['data'] = {
firstName: '',
lastName: '',
country: '',
address1: '',
address2: '',
landmark: '',
city: '',
state: '',
zipCode: ''
}
const customInputData: CustomInputVerticalData[] = [
{
title: 'Home',
content: 'Delivery Time (7am - 9pm)',
value: 'home',
isSelected: true,
asset: 'tabler-home'
},
{
title: 'Office',
content: 'Delivery Time (10am - 6pm)',
value: 'office',
asset: 'tabler-building-skyscraper'
}
]
const AddEditAddress = ({ open, setOpen, data }: AddEditAddressProps) => {
// Vars
const initialSelected: string = customInputData?.find(item => item.isSelected)?.value || ''
// States
const [selected, setSelected] = useState<string>(initialSelected)
const [addressData, setAddressData] = useState<AddEditAddressProps['data']>(initialAddressData)
const handleChange = (prop: string | ChangeEvent<HTMLInputElement>) => {
if (typeof prop === 'string') {
setSelected(prop)
} else {
setSelected((prop.target as HTMLInputElement).value)
}
}
useEffect(() => {
setAddressData(data ?? initialAddressData)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [open])
return (
<Dialog
open={open}
maxWidth='md'
scroll='body'
onClose={() => {
setOpen(false)
setSelected(initialSelected)
}}
closeAfterTransition={false}
sx={{ '& .MuiDialog-paper': { overflow: 'visible' } }}
>
<DialogTitle variant='h4' className='flex gap-2 flex-col text-center sm:pbs-16 sm:pbe-6 sm:pli-16'>
{data ? 'Edit Address' : 'Add New Address'}
<Typography component='span' className='flex flex-col text-center'>
{data ? 'Edit Address for future billing' : 'Add address for billing address'}
</Typography>
</DialogTitle>
<form onSubmit={e => e.preventDefault()}>
<DialogContent className='pbs-0 sm:pli-16'>
<DialogCloseButton onClick={() => setOpen(false)} disableRipple>
<i className='tabler-x' />
</DialogCloseButton>
<Grid container spacing={6}>
{customInputData.map((item, index) => {
let asset
if (item.asset && typeof item.asset === 'string') {
asset = <i className={classnames(item.asset, 'text-[28px]')} />
}
return (
<Grid size={{ xs: 12, sm: 6 }} key={index}>
<CustomInputVertical
type='radio'
key={index}
data={{ ...item, asset }}
selected={selected}
name='addressType'
handleChange={handleChange}
/>
</Grid>
)
})}
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='First Name'
name='firstName'
variant='outlined'
placeholder='John'
value={addressData?.firstName}
onChange={e => setAddressData({ ...addressData, firstName: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='Last Name'
name='lastName'
variant='outlined'
placeholder='Doe'
value={addressData?.lastName}
onChange={e => setAddressData({ ...addressData, lastName: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12 }}>
<CustomTextField
select
fullWidth
label='Country'
name='country'
variant='outlined'
value={addressData?.country?.toLowerCase().replace(/\s+/g, '-') || ''}
onChange={e => setAddressData({ ...addressData, country: e.target.value })}
>
{countries.map((item, index) => (
<MenuItem key={index} value={index === 0 ? '' : item.toLowerCase().replace(/\s+/g, '-')}>
{item}
</MenuItem>
))}
</CustomTextField>
</Grid>
<Grid size={{ xs: 12 }}>
<CustomTextField
fullWidth
label='Address Line 1'
name='address1'
variant='outlined'
placeholder='12, Business Park'
value={addressData?.address1}
onChange={e => setAddressData({ ...addressData, address1: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12 }}>
<CustomTextField
fullWidth
label='Address Line 2'
name='address1'
variant='outlined'
placeholder='Mall Road'
value={addressData?.address2}
onChange={e => setAddressData({ ...addressData, address2: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='Landmark'
name='landmark'
variant='outlined'
placeholder='Nr. Hard Rock Cafe'
value={addressData?.landmark}
onChange={e => setAddressData({ ...addressData, landmark: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='City'
name='city'
variant='outlined'
placeholder='Los Angeles'
value={addressData?.city}
onChange={e => setAddressData({ ...addressData, city: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='State'
name='state'
variant='outlined'
placeholder='California'
value={addressData?.state}
onChange={e => setAddressData({ ...addressData, state: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='Zip Code'
type='number'
name='zipCode'
variant='outlined'
placeholder='99950'
value={addressData?.zipCode}
onChange={e => setAddressData({ ...addressData, zipCode: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12 }}>
<FormControlLabel control={<Switch defaultChecked />} label='Make this default shipping address' />
</Grid>
</Grid>
</DialogContent>
<DialogActions className='justify-center pbs-0 sm:pbe-16 sm:pli-16'>
<Button variant='contained' onClick={() => setOpen(false)} type='submit'>
{data ? 'Update' : 'Submit'}
</Button>
<Button
variant='tonal'
color='secondary'
onClick={() => {
setOpen(false)
setSelected(initialSelected)
}}
type='reset'
>
Cancel
</Button>
</DialogActions>
</form>
</Dialog>
)
}
export default AddEditAddress
@@ -0,0 +1,147 @@
'use client'
// React Imports
import { useEffect, useState } from 'react'
// MUI Imports
import Grid from '@mui/material/Grid2'
import Dialog from '@mui/material/Dialog'
import Button from '@mui/material/Button'
import Switch from '@mui/material/Switch'
import DialogTitle from '@mui/material/DialogTitle'
import DialogContent from '@mui/material/DialogContent'
import DialogActions from '@mui/material/DialogActions'
import FormControlLabel from '@mui/material/FormControlLabel'
import Typography from '@mui/material/Typography'
// Type Imports
import type { ThemeColor } from '@core/types'
// Component Imports
import DialogCloseButton from '../DialogCloseButton'
import CustomTextField from '@core/components/mui/TextField'
type BillingCardData = {
cardNumber?: string
name?: string
expiryDate?: string
cardCvv?: string
imgSrc?: string
imgAlt?: string
cardStatus?: string
badgeColor?: ThemeColor
}
type BillingCardProps = {
open: boolean
setOpen: (open: boolean) => void
data?: BillingCardData
}
const initialCardData: BillingCardProps['data'] = {
cardNumber: '',
name: '',
expiryDate: '',
cardCvv: '',
imgSrc: '',
imgAlt: '',
cardStatus: '',
badgeColor: 'primary'
}
const BillingCard = ({ open, setOpen, data }: BillingCardProps) => {
// States
const [cardData, setCardData] = useState(initialCardData)
const handleClose = () => {
setOpen(false)
setCardData(initialCardData)
}
useEffect(() => {
setCardData(data ?? initialCardData)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [open])
return (
<Dialog
open={open}
onClose={handleClose}
closeAfterTransition={false}
sx={{ '& .MuiDialog-paper': { overflow: 'visible' } }}
>
<DialogCloseButton onClick={() => setOpen(false)} disableRipple>
<i className='tabler-x' />
</DialogCloseButton>
<DialogTitle variant='h4' className='flex flex-col gap-2 text-center p-6 sm:pbs-16 sm:pbe-6 sm:pli-16'>
{data ? 'Edit Card' : 'Add New Card'}
<Typography component='span' className='flex flex-col text-center'>
{data ? 'Edit your saved card details' : 'Add card for future billing'}
</Typography>
</DialogTitle>
<form onSubmit={e => e.preventDefault()}>
<DialogContent className='overflow-visible pbs-0 p-6 sm:pli-16'>
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<CustomTextField
fullWidth
name='number'
autoComplete='off'
label='Card Number'
placeholder='0000 0000 0000 0000'
value={cardData.cardNumber}
onChange={e => setCardData({ ...cardData, cardNumber: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
name='name'
label='Name on Card'
autoComplete='off'
placeholder='John Doe'
value={cardData.name}
onChange={e => setCardData({ ...cardData, name: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 6, sm: 3 }}>
<CustomTextField
fullWidth
name='expiry'
autoComplete='off'
label='Expiry'
placeholder='MM/YY'
value={cardData.expiryDate}
onChange={e => setCardData({ ...cardData, expiryDate: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 6, sm: 3 }}>
<CustomTextField
fullWidth
name='cvv'
label='CVV'
autoComplete='off'
placeholder='123'
value={cardData.cardCvv}
onChange={e => setCardData({ ...cardData, cardCvv: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12 }}>
<FormControlLabel control={<Switch defaultChecked />} label='Save Card for future billing?' />
</Grid>
</Grid>
</DialogContent>
<DialogActions className='justify-center pbs-0 p-6 sm:pbe-16 sm:pli-16'>
<Button variant='contained' type='submit' onClick={handleClose}>
{data ? 'Update' : 'Submit'}
</Button>
<Button variant='tonal' type='reset' color='secondary' onClick={handleClose}>
Cancel
</Button>
</DialogActions>
</form>
</Dialog>
)
}
export default BillingCard
@@ -0,0 +1,139 @@
'use client'
// React Imports
import { Fragment, useState } from 'react'
// MUI Imports
import Dialog from '@mui/material/Dialog'
import DialogContent from '@mui/material/DialogContent'
import DialogActions from '@mui/material/DialogActions'
import Typography from '@mui/material/Typography'
import Button from '@mui/material/Button'
// Third-party Imports
import classnames from 'classnames'
type ConfirmationType = 'delete-account' | 'unsubscribe' | 'suspend-account' | 'delete-order' | 'delete-customer'
type ConfirmationDialogProps = {
open: boolean
setOpen: (open: boolean) => void
type: ConfirmationType
}
const ConfirmationDialog = ({ open, setOpen, type }: ConfirmationDialogProps) => {
// States
const [secondDialog, setSecondDialog] = useState(false)
const [userInput, setUserInput] = useState(false)
// Vars
const Wrapper = type === 'suspend-account' ? 'div' : Fragment
const handleSecondDialogClose = () => {
setSecondDialog(false)
setOpen(false)
}
const handleConfirmation = (value: boolean) => {
setUserInput(value)
setSecondDialog(true)
setOpen(false)
}
return (
<>
<Dialog fullWidth maxWidth='xs' open={open} onClose={() => setOpen(false)} closeAfterTransition={false}>
<DialogContent className='flex items-center flex-col text-center sm:pbs-16 sm:pbe-6 sm:pli-16'>
<i className='tabler-alert-circle text-[88px] mbe-6 text-warning' />
<Wrapper
{...(type === 'suspend-account' && {
className: 'flex flex-col items-center gap-2'
})}
>
<Typography variant='h4'>
{type === 'delete-account' && 'Are you sure you want to deactivate your account?'}
{type === 'unsubscribe' && 'Are you sure to cancel your subscription?'}
{type === 'suspend-account' && 'Are you sure?'}
{type === 'delete-order' && 'Are you sure?'}
{type === 'delete-customer' && 'Are you sure?'}
</Typography>
{type === 'suspend-account' && (
<Typography color='text.primary'>You won&#39;t be able to revert user!</Typography>
)}
{type === 'delete-order' && (
<Typography color='text.primary'>You won&#39;t be able to revert order!</Typography>
)}
{type === 'delete-customer' && (
<Typography color='text.primary'>You won&#39;t be able to revert customer!</Typography>
)}
</Wrapper>
</DialogContent>
<DialogActions className='justify-center pbs-0 sm:pbe-16 sm:pli-16'>
<Button variant='contained' onClick={() => handleConfirmation(true)}>
{type === 'suspend-account'
? 'Yes, Suspend User!'
: type === 'delete-order'
? 'Yes, Delete Order!'
: type === 'delete-customer'
? 'Yes, Delete Customer!'
: 'Yes'}
</Button>
<Button
variant='tonal'
color='secondary'
onClick={() => {
handleConfirmation(false)
}}
>
Cancel
</Button>
</DialogActions>
</Dialog>
{/* Delete Account Dialog */}
<Dialog open={secondDialog} onClose={handleSecondDialogClose} closeAfterTransition={false}>
<DialogContent className='flex items-center flex-col text-center sm:pbs-16 sm:pbe-6 sm:pli-16'>
<i
className={classnames('text-[88px] mbe-6', {
'tabler-circle-check': userInput,
'text-success': userInput,
'tabler-circle-x': !userInput,
'text-error': !userInput
})}
/>
<Typography variant='h4' className='mbe-2'>
{userInput
? `${type === 'delete-account' ? 'Deactivated' : type === 'unsubscribe' ? 'Unsubscribed' : type === 'delete-order' || 'delete-customer' ? 'Deleted' : 'Suspended!'}`
: 'Cancelled'}
</Typography>
<Typography color='text.primary'>
{userInput ? (
<>
{type === 'delete-account' && 'Your account has been deactivated successfully.'}
{type === 'unsubscribe' && 'Your subscription cancelled successfully.'}
{type === 'suspend-account' && 'User has been suspended.'}
{type === 'delete-order' && 'Your order deleted successfully.'}
{type === 'delete-customer' && 'Your customer removed successfully.'}
</>
) : (
<>
{type === 'delete-account' && 'Account Deactivation Cancelled!'}
{type === 'unsubscribe' && 'Unsubscription Cancelled!!'}
{type === 'suspend-account' && 'Cancelled Suspension :)'}
{type === 'delete-order' && 'Order Deletion Cancelled'}
{type === 'delete-customer' && 'Customer Deletion Cancelled'}
</>
)}
</Typography>
</DialogContent>
<DialogActions className='justify-center pbs-0 sm:pbe-16 sm:pli-16'>
<Button variant='contained' color='success' onClick={handleSecondDialogClose}>
Ok
</Button>
</DialogActions>
</Dialog>
</>
)
}
export default ConfirmationDialog
@@ -0,0 +1,112 @@
// React Imports
import { useState } from 'react'
// MUI Imports
import Grid from '@mui/material/Grid2'
import FormControlLabel from '@mui/material/FormControlLabel'
import Switch from '@mui/material/Switch'
import Button from '@mui/material/Button'
import Typography from '@mui/material/Typography'
// Component Imports
import CustomTextField from '@core/components/mui/TextField'
import DirectionalIcon from '@components/DirectionalIcon'
type Props = {
activeStep: number
isLastStep: boolean
handleNext: () => void
handlePrev: () => void
}
const Billing = ({ activeStep, isLastStep, handleNext, handlePrev }: Props) => {
// States
const [cardData, setCardData] = useState({
number: '',
name: '',
expiry: '',
cvv: ''
})
return (
<div className='flex flex-col gap-6'>
<Typography variant='h5'>Payment Details</Typography>
<Grid container spacing={6}>
<Grid size={{ xs: 12 }}>
<CustomTextField
fullWidth
name='number'
autoComplete='off'
label='Card Number'
placeholder='0000 0000 0000 0000'
value={cardData.number}
onChange={e => setCardData({ ...cardData, number: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
name='name'
label='Name on Card'
autoComplete='off'
placeholder='John Doe'
value={cardData.name}
onChange={e => setCardData({ ...cardData, name: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 6, sm: 3 }}>
<CustomTextField
fullWidth
name='expiry'
autoComplete='off'
label='Expiry'
placeholder='MM/YY'
value={cardData.expiry}
onChange={e => setCardData({ ...cardData, expiry: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 6, sm: 3 }}>
<CustomTextField
fullWidth
name='cvv'
label='CVV'
autoComplete='off'
placeholder='123'
value={cardData.cvv}
onChange={e => setCardData({ ...cardData, cvv: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12 }}>
<FormControlLabel control={<Switch defaultChecked />} label='Save Card for future billing?' />
</Grid>
<Grid size={{ xs: 12 }} className='flex items-center justify-between'>
<Button
variant='tonal'
color='secondary'
disabled={activeStep === 0}
onClick={handlePrev}
startIcon={<DirectionalIcon ltrIconClass='tabler-arrow-left' rtlIconClass='tabler-arrow-right' />}
>
Previous
</Button>
<Button
variant='contained'
color={isLastStep ? 'success' : 'primary'}
onClick={handleNext}
endIcon={
isLastStep ? (
<i className='tabler-check' />
) : (
<DirectionalIcon ltrIconClass='tabler-arrow-right' rtlIconClass='tabler-arrow-left' />
)
}
>
{isLastStep ? 'Submit' : 'Next'}
</Button>
</Grid>
</Grid>
</div>
)
}
export default Billing
@@ -0,0 +1,114 @@
// React Imports
import { useState } from 'react'
import type { ChangeEvent } from 'react'
// MUI Imports
import Typography from '@mui/material/Typography'
import Radio from '@mui/material/Radio'
import Button from '@mui/material/Button'
// Component Imports
import CustomAvatar from '@core/components/mui/Avatar'
import CustomTextField from '@core/components/mui/TextField'
import DirectionalIcon from '@components/DirectionalIcon'
// Config Imports
import themeConfig from '@configs/themeConfig'
type Props = {
activeStep: number
isLastStep: boolean
handleNext: () => void
handlePrev: () => void
}
const DataBase = ({ activeStep, isLastStep, handleNext, handlePrev }: Props) => {
// States
const [value, setValue] = useState<string>('firebase')
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setValue(event.target.value)
}
return (
<div className='flex flex-col gap-6'>
<CustomTextField
fullWidth
label='Database Name'
placeholder={`${themeConfig.templateName.toLowerCase().replace(/\s+/g, '_')}_database`}
/>
<div className='flex flex-col gap-4'>
<Typography variant='h5'>Select Database Engine</Typography>
<div onClick={() => setValue('firebase')} className='flex items-center justify-between cursor-pointer gap-4'>
<div className='flex items-center gap-3'>
<CustomAvatar skin='light' color='warning' variant='rounded' size={46}>
<img src='/images/logos/firebase.png' alt='firebase' height={30} width={30} />
</CustomAvatar>
<div className='flex flex-col gap-1'>
<Typography color='text.primary' className='font-medium'>
Firebase
</Typography>
<Typography variant='body2'>Cloud Firestore</Typography>
</div>
</div>
<Radio value='firebase' onChange={handleChange} checked={value === 'firebase'} />
</div>
<div onClick={() => setValue('aws')} className='flex items-center justify-between cursor-pointer gap-4'>
<div className='flex items-center gap-3'>
<CustomAvatar skin='light' color='secondary' variant='rounded' size={46}>
<img src='/images/logos/aws.png' alt='aws' height={30} width={30} />
</CustomAvatar>
<div className='flex flex-col gap-1'>
<Typography color='text.primary' className='font-medium'>
AWS
</Typography>
<Typography variant='body2'>Amazon Fast NoSQL Database</Typography>
</div>
</div>
<Radio value='aws' onChange={handleChange} checked={value === 'aws'} />
</div>
<div onClick={() => setValue('sql')} className='flex items-center justify-between cursor-pointer gap-4'>
<div className='flex items-center gap-3'>
<CustomAvatar skin='light' color='info' variant='rounded' size={46}>
<i className='tabler-database text-3xl' />
</CustomAvatar>
<div className='flex flex-col gap-1'>
<Typography color='text.primary' className='font-medium'>
MySQL
</Typography>
<Typography variant='body2'>Basic MySQL database</Typography>
</div>
</div>
<Radio value='sql' onChange={handleChange} checked={value === 'sql'} />
</div>
</div>
<div className='flex items-center justify-between'>
<Button
variant='tonal'
color='secondary'
disabled={activeStep === 0}
onClick={handlePrev}
startIcon={<DirectionalIcon ltrIconClass='tabler-arrow-left' rtlIconClass='tabler-arrow-right' />}
>
Previous
</Button>
<Button
variant='contained'
color={isLastStep ? 'success' : 'primary'}
onClick={handleNext}
endIcon={
isLastStep ? (
<i className='tabler-check' />
) : (
<DirectionalIcon ltrIconClass='tabler-arrow-right' rtlIconClass='tabler-arrow-left' />
)
}
>
{isLastStep ? 'Submit' : 'Next'}
</Button>
</div>
</div>
)
}
export default DataBase
@@ -0,0 +1,110 @@
// React Imports
import { useState } from 'react'
import type { ChangeEvent } from 'react'
// MUI Imports
import Radio from '@mui/material/Radio'
import Typography from '@mui/material/Typography'
import Button from '@mui/material/Button'
// Component Imports
import CustomAvatar from '@core/components/mui/Avatar'
import CustomTextField from '@core/components/mui/TextField'
import DirectionalIcon from '@components/DirectionalIcon'
// Config Imports
import themeConfig from '@configs/themeConfig'
type Props = {
activeStep: number
isLastStep: boolean
handleNext: () => void
handlePrev: () => void
}
const Details = ({ activeStep, isLastStep, handleNext, handlePrev }: Props) => {
// States
const [value, setValue] = useState<string>('crm')
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setValue(event.target.value)
}
return (
<div className='flex flex-col gap-6'>
<CustomTextField fullWidth label='Application Name' placeholder={`${themeConfig.templateName}`} />
<div className='flex flex-col gap-4'>
<Typography variant='h5'>Category</Typography>
<div onClick={() => setValue('crm')} className='flex items-center justify-between cursor-pointer gap-4'>
<div className='flex items-center gap-3'>
<CustomAvatar skin='light' color='info' variant='rounded' size={46}>
<i className='tabler-file-text text-3xl' />
</CustomAvatar>
<div className='flex flex-col gap-1'>
<Typography color='text.primary' className='font-medium'>
CRM Application
</Typography>
<Typography variant='body2'>Scales with any business</Typography>
</div>
</div>
<Radio value='crm' onChange={handleChange} checked={value === 'crm'} />
</div>
<div onClick={() => setValue('eCommerce')} className='flex items-center justify-between cursor-pointer gap-4'>
<div className='flex items-center gap-3'>
<CustomAvatar skin='light' color='success' variant='rounded' size={46}>
<i className='tabler-shopping-cart text-3xl' />
</CustomAvatar>
<div className='flex flex-col gap-1'>
<Typography color='text.primary' className='font-medium'>
eCommerce Platforms
</Typography>
<Typography variant='body2'>Grow Your Business With App</Typography>
</div>
</div>
<Radio value='eCommerce' onChange={handleChange} checked={value === 'eCommerce'} />
</div>
<div onClick={() => setValue('learning')} className='flex items-center justify-between cursor-pointer gap-4'>
<div className='flex items-center gap-3'>
<CustomAvatar skin='light' color='error' variant='rounded' size={46}>
<i className='tabler-device-laptop text-3xl' />
</CustomAvatar>
<div className='flex flex-col gap-1'>
<Typography color='text.primary' className='font-medium'>
Online Learning platform
</Typography>
<Typography variant='body2'>Start learning today</Typography>
</div>
</div>
<Radio value='learning' onChange={handleChange} checked={value === 'learning'} />
</div>
</div>
<div className='flex items-center justify-between'>
<Button
variant='tonal'
color='secondary'
disabled={activeStep === 0}
onClick={handlePrev}
startIcon={<DirectionalIcon ltrIconClass='tabler-arrow-left' rtlIconClass='tabler-arrow-right' />}
>
Previous
</Button>
<Button
variant='contained'
color={isLastStep ? 'success' : 'primary'}
onClick={handleNext}
endIcon={
isLastStep ? (
<i className='tabler-check' />
) : (
<DirectionalIcon ltrIconClass='tabler-arrow-right' rtlIconClass='tabler-arrow-left' />
)
}
>
{isLastStep ? 'Submit' : 'Next'}
</Button>
</div>
</div>
)
}
export default Details
@@ -0,0 +1,120 @@
// React Imports
import { useState } from 'react'
import type { ChangeEvent } from 'react'
// MUI Imports
import Typography from '@mui/material/Typography'
import Radio from '@mui/material/Radio'
import Button from '@mui/material/Button'
// Component Imports
import CustomAvatar from '@core/components/mui/Avatar'
import DirectionalIcon from '@components/DirectionalIcon'
type Props = {
activeStep: number
isLastStep: boolean
handleNext: () => void
handlePrev: () => void
}
const FrameWork = ({ activeStep, isLastStep, handleNext, handlePrev }: Props) => {
// States
const [value, setValue] = useState<string>('react')
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setValue(event.target.value)
}
return (
<div className='flex flex-col gap-6'>
<div className='flex flex-col gap-4'>
<Typography variant='h5'>Select Framework</Typography>
<div onClick={() => setValue('react')} className='flex items-center justify-between cursor-pointer gap-4'>
<div className='flex items-center gap-3'>
<CustomAvatar skin='light' color='info' variant='rounded' size={46}>
<img src='/images/logos/react.png' alt='react' height={30} width={30} />
</CustomAvatar>
<div className='flex flex-col gap-1'>
<Typography color='text.primary' className='font-medium'>
React Native
</Typography>
<Typography variant='body2'>Create truly native apps</Typography>
</div>
</div>
<Radio value='react' onChange={handleChange} checked={value === 'react'} />
</div>
<div onClick={() => setValue('angular')} className='flex items-center justify-between cursor-pointer gap-4'>
<div className='flex items-center gap-3'>
<CustomAvatar skin='light' color='error' variant='rounded' size={46}>
<img src='/images/logos/angular.png' alt='angular' height={30} width={30} />
</CustomAvatar>
<div className='flex flex-col gap-1'>
<Typography color='text.primary' className='font-medium'>
Angular
</Typography>
<Typography variant='body2'>Most suited for your application</Typography>
</div>
</div>
<Radio value='angular' onChange={handleChange} checked={value === 'angular'} />
</div>
<div onClick={() => setValue('vuejs')} className='flex items-center justify-between cursor-pointer gap-4'>
<div className='flex items-center gap-3'>
<CustomAvatar skin='light' color='success' variant='rounded' size={46}>
<img src='/images/logos/vue.png' alt='vue' height={30} width={30} />
</CustomAvatar>
<div className='flex flex-col gap-1'>
<Typography color='text.primary' className='font-medium'>
Vue
</Typography>
<Typography variant='body2'>Progressive Framework</Typography>
</div>
</div>
<Radio value='vuejs' onChange={handleChange} checked={value === 'vuejs'} />
</div>
<div onClick={() => setValue('laravel')} className='flex items-center justify-between cursor-pointer gap-4'>
<div className='flex items-center gap-3'>
<CustomAvatar skin='light' color='warning' variant='rounded'>
<img src='/images/logos/laravel.png' alt='laravel' height={30} width={30} />
</CustomAvatar>
<div className='flex flex-col gap-1'>
<Typography color='text.primary' className='font-medium'>
Laravel
</Typography>
<Typography variant='body2'>PHP web frameworks</Typography>
</div>
</div>
<Radio value='laravel' onChange={handleChange} checked={value === 'laravel'} />
</div>
</div>
<div className='flex items-center justify-between'>
<Button
variant='tonal'
color='secondary'
disabled={activeStep === 0}
onClick={handlePrev}
startIcon={<DirectionalIcon ltrIconClass='tabler-arrow-left' rtlIconClass='tabler-arrow-right' />}
>
Previous
</Button>
<Button
variant='contained'
color={isLastStep ? 'success' : 'primary'}
onClick={handleNext}
endIcon={
isLastStep ? (
<i className='tabler-check' />
) : (
<DirectionalIcon ltrIconClass='tabler-arrow-right' rtlIconClass='tabler-arrow-left' />
)
}
>
{isLastStep ? 'Submit' : 'Next'}
</Button>
</div>
</div>
)
}
export default FrameWork
@@ -0,0 +1,54 @@
// MUI Imports
import Typography from '@mui/material/Typography'
import Button from '@mui/material/Button'
// Component Imports
import DirectionalIcon from '@components/DirectionalIcon'
type Props = {
activeStep: number
isLastStep: boolean
handleNext: () => void
handlePrev: () => void
}
const Submit = ({ activeStep, isLastStep, handleNext, handlePrev }: Props) => {
return (
<div className='flex flex-col gap-6'>
<div className='flex flex-col items-center gap-4'>
<div className='flex flex-col items-center gap-1'>
<Typography variant='h5'>Submit</Typography>
<Typography variant='body2'>Submit to kickstart your project.</Typography>
</div>
<img alt='submit-img' src='/images/illustrations/characters/4.png' height={200} width={176} />
</div>
<div className='flex items-center justify-between'>
<Button
variant='tonal'
color='secondary'
disabled={activeStep === 0}
onClick={handlePrev}
startIcon={<DirectionalIcon ltrIconClass='tabler-arrow-left' rtlIconClass='tabler-arrow-right' />}
>
Previous
</Button>
<Button
variant='contained'
color={isLastStep ? 'success' : 'primary'}
onClick={handleNext}
endIcon={
isLastStep ? (
<i className='tablerr-check' />
) : (
<DirectionalIcon ltrIconClass='tabler-arrow-right' rtlIconClass='tabler-arrow-left' />
)
}
>
{isLastStep ? 'Submit' : 'Next'}
</Button>
</div>
</div>
)
}
export default Submit
+182
View File
@@ -0,0 +1,182 @@
'use client'
// React Imports
import { useState } from 'react'
// MUI Imports
import { styled } from '@mui/material/styles'
import Dialog from '@mui/material/Dialog'
import DialogTitle from '@mui/material/DialogTitle'
import DialogContent from '@mui/material/DialogContent'
import Typography from '@mui/material/Typography'
import MuiStep from '@mui/material/Step'
import StepLabel from '@mui/material/StepLabel'
import Stepper from '@mui/material/Stepper'
import type { StepProps } from '@mui/material/Step'
// Third-party Imports
import classnames from 'classnames'
// Component Imports
import Billing from './Billing'
import CustomAvatar from '@core/components/mui/Avatar'
import Details from './Details'
import DialogCloseButton from '../DialogCloseButton'
import Database from './Database'
import FrameWork from './FrameWork'
import Submit from './Submit'
// Styled Component Imports
import StepperWrapper from '@core/styles/stepper'
type CreateAppProps = {
open: boolean
setOpen: (open: boolean) => void
}
type stepperProps = {
icon: string
title: string
subtitle: string
active?: boolean
}
const steps: stepperProps[] = [
{
icon: 'tabler-file-text',
title: 'Details',
subtitle: 'Enter Details'
},
{
icon: 'tabler-id',
title: 'FrameWorks',
subtitle: 'Select Framework',
active: true
},
{
icon: 'tabler-database',
title: 'Database',
subtitle: 'Select Database'
},
{
icon: 'tabler-credit-card',
title: 'Billing',
subtitle: 'Payment Details'
},
{
icon: 'tabler-check',
title: 'Submit',
subtitle: 'Submit'
}
]
const Step = styled(MuiStep)<StepProps>({
'&.Mui-completed .step-title , &.Mui-completed .step-subtitle': {
color: 'var(--mui-palette-text-disabled)'
}
})
const renderStepCount = (activeStep: number, isLastStep: boolean, handleNext: () => void, handlePrev: () => void) => {
const Tag =
activeStep === 0
? Details
: activeStep === 1
? FrameWork
: activeStep === 2
? Database
: activeStep === 3
? Billing
: Submit
return <Tag activeStep={activeStep} handleNext={handleNext} handlePrev={handlePrev} isLastStep={isLastStep} />
}
const CreateApp = ({ open, setOpen }: CreateAppProps) => {
// States
const [activeStep, setActiveStep] = useState(0)
const handleClose = () => {
setOpen(false)
setActiveStep(0)
}
const handleStep = (step: number) => () => {
setActiveStep(step)
}
// Vars
const isLastStep = activeStep === steps.length - 1
const handleNext = () => {
if (!isLastStep) {
setActiveStep(prevActiveStep => prevActiveStep + 1)
} else {
handleClose()
}
}
const handlePrev = () => {
setActiveStep(prevActiveStep => prevActiveStep - 1)
}
return (
<Dialog
fullWidth
maxWidth='md'
open={open}
onClose={handleClose}
scroll='body'
closeAfterTransition={false}
sx={{ '& .MuiDialog-paper': { overflow: 'visible' } }}
>
<DialogCloseButton onClick={() => setOpen(false)} disableRipple>
<i className='tabler-x' />
</DialogCloseButton>
<DialogTitle variant='h4' className='flex gap-2 flex-col text-center sm:pbs-16 sm:pbe-6 sm:pli-16'>
Create App
<Typography component='span' className='flex flex-col text-center'>
Provide data with this form to create your app.
</Typography>
</DialogTitle>
<DialogContent className='pbs-0 sm:pli-16 sm:pbe-16'>
<div className='flex gap-y-6 flex-col md:flex-row md:gap-5'>
<StepperWrapper>
<Stepper
activeStep={activeStep}
orientation='vertical'
connector={<></>}
className='flex flex-col gap-4 min-is-[220px]'
>
{steps.map((label, index) => {
return (
<Step key={index} onClick={handleStep(index)}>
<StepLabel icon={<></>} className='p-1 cursor-pointer'>
<div className='step-label'>
<CustomAvatar
variant='rounded'
skin={activeStep === index ? 'filled' : 'light'}
{...(activeStep >= index && { color: 'primary' })}
{...(activeStep === index && { className: 'shadow-primarySm' })}
size={38}
>
<i className={classnames(label.icon as string, 'text-[22px]')} />
</CustomAvatar>
<div className='flex flex-col'>
<Typography className='uppercase step-title'>{label.title}</Typography>
<Typography className='step-subtitle'>{label.subtitle}</Typography>
</div>
</div>
</StepLabel>
</Step>
)
})}
</Stepper>
</StepperWrapper>
<div className='flex-1'>{renderStepCount(activeStep, isLastStep, handleNext, handlePrev)}</div>
</div>
</DialogContent>
</Dialog>
)
}
export default CreateApp
@@ -0,0 +1,224 @@
'use client'
// React Imports
import { useState } from 'react'
// MUI Imports
import Grid from '@mui/material/Grid2'
import Dialog from '@mui/material/Dialog'
import Button from '@mui/material/Button'
import DialogTitle from '@mui/material/DialogTitle'
import DialogContent from '@mui/material/DialogContent'
import DialogActions from '@mui/material/DialogActions'
import Chip from '@mui/material/Chip'
import MenuItem from '@mui/material/MenuItem'
import Typography from '@mui/material/Typography'
import Switch from '@mui/material/Switch'
import { FormControlLabel } from '@mui/material'
// Component Imports
import DialogCloseButton from '../DialogCloseButton'
import CustomTextField from '@core/components/mui/TextField'
type EditUserInfoData = {
firstName?: string
lastName?: string
userName?: string
billingEmail?: string
status?: string
taxId?: string
contact?: string
language?: string[]
country?: string
useAsBillingAddress?: boolean
}
type EditUserInfoProps = {
open: boolean
setOpen: (open: boolean) => void
data?: EditUserInfoData
}
const initialData: EditUserInfoProps['data'] = {
firstName: 'Oliver',
lastName: 'Queen',
userName: 'oliverQueen',
billingEmail: 'oliverQueen@gmail.com',
status: 'active',
taxId: 'Tax-8894',
contact: '+ 1 609 933 4422',
language: ['English'],
country: 'US',
useAsBillingAddress: true
}
const status = ['Status', 'Active', 'Inactive', 'Suspended']
const languages = ['English', 'Spanish', 'French', 'German', 'Hindi']
const countries = ['Select Country', 'France', 'Russia', 'China', 'UK', 'US']
const EditUserInfo = ({ open, setOpen, data }: EditUserInfoProps) => {
// States
const [userData, setUserData] = useState<EditUserInfoProps['data']>(data || initialData)
const handleClose = () => {
setOpen(false)
setUserData(data || initialData)
}
return (
<Dialog
fullWidth
open={open}
onClose={handleClose}
maxWidth='md'
scroll='body'
closeAfterTransition={false}
sx={{ '& .MuiDialog-paper': { overflow: 'visible' } }}
>
<DialogCloseButton onClick={() => setOpen(false)} disableRipple>
<i className='tabler-x' />
</DialogCloseButton>
<DialogTitle variant='h4' className='flex gap-2 flex-col text-center sm:pbs-16 sm:pbe-6 sm:pli-16'>
Edit User Information
<Typography component='span' className='flex flex-col text-center'>
Updating user details will receive a privacy audit.
</Typography>
</DialogTitle>
<form onSubmit={e => e.preventDefault()}>
<DialogContent className='overflow-visible pbs-0 sm:pli-16'>
<Grid container spacing={5}>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='First Name'
placeholder='John'
value={userData?.firstName}
onChange={e => setUserData({ ...userData, firstName: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='Last Name'
placeholder='Doe'
value={userData?.lastName}
onChange={e => setUserData({ ...userData, lastName: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12 }}>
<CustomTextField
fullWidth
label='User Name'
placeholder='JohnDoe'
value={userData?.userName}
onChange={e => setUserData({ ...userData, userName: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='Billing Email'
placeholder='johnDoe@email.com'
value={userData?.billingEmail}
onChange={e => setUserData({ ...userData, billingEmail: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
select
fullWidth
label='Status'
value={userData?.status}
onChange={e => setUserData({ ...userData, status: e.target.value as string })}
>
{status.map((status, index) => (
<MenuItem key={index} value={index === 0 ? '' : status.toLowerCase().replace(/\s+/g, '-')}>
{status}
</MenuItem>
))}
</CustomTextField>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='Tax ID'
placeholder='Tax-7490'
value={userData?.taxId}
onChange={e => setUserData({ ...userData, taxId: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
fullWidth
label='Contact'
placeholder='+ 123 456 7890'
value={userData?.contact}
onChange={e => setUserData({ ...userData, contact: e.target.value })}
/>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
select
fullWidth
label='Language'
value={userData?.language?.map(lang => lang.toLowerCase().replace(/\s+/g, '-')) || []}
slotProps={{
select: {
multiple: true,
onChange: e => setUserData({ ...userData, language: e.target.value as string[] }),
renderValue: selected => (
<div className='flex items-center gap-2'>
{(selected as string[]).map(value => (
<Chip key={value} label={value} className='capitalize' size='small' />
))}
</div>
)
}
}}
>
{languages.map((language, index) => (
<MenuItem key={index} value={language.toLowerCase().replace(/\s+/g, '-')}>
{language}
</MenuItem>
))}
</CustomTextField>
</Grid>
<Grid size={{ xs: 12, sm: 6 }}>
<CustomTextField
select
fullWidth
label='Country'
value={userData?.country?.toLowerCase().replace(/\s+/g, '-')}
onChange={e => setUserData({ ...userData, country: e.target.value as string })}
>
{countries.map((country, index) => (
<MenuItem key={index} value={index === 0 ? '' : country.toLowerCase().replace(/\s+/g, '-')}>
{country}
</MenuItem>
))}
</CustomTextField>
</Grid>
<Grid size={{ xs: 12 }}>
<FormControlLabel
control={<Switch defaultChecked={userData?.useAsBillingAddress} />}
label='Use as a billing address?'
/>
</Grid>
</Grid>
</DialogContent>
<DialogActions className='justify-center pbs-0 sm:pbe-16 sm:pli-16'>
<Button variant='contained' onClick={handleClose} type='submit'>
Submit
</Button>
<Button variant='tonal' color='secondary' type='reset' onClick={handleClose}>
Cancel
</Button>
</DialogActions>
</form>
</Dialog>
)
}
export default EditUserInfo
@@ -0,0 +1,122 @@
'use client'
// MUI Imports
import Avatar from '@mui/material/Avatar'
import Dialog from '@mui/material/Dialog'
import DialogContent from '@mui/material/DialogContent'
import DialogTitle from '@mui/material/DialogTitle'
import Typography from '@mui/material/Typography'
import { useColorScheme } from '@mui/material/styles'
// Third-party Imports
import classnames from 'classnames'
// Component Imports
import DialogCloseButton from '../DialogCloseButton'
type PaymentMethodProps = {
open: boolean
setOpen: (open: boolean) => void
}
type CardList = {
image: string
imgWidth: string
imgHeight?: string
alt: string
cardName: string
cardType: string
}
const cardList: CardList[] = [
{
image: '/images/logos/visa.png',
imgWidth: '30px',
alt: 'visa card',
cardName: 'Visa',
cardType: 'Credit Card'
},
{
image: '/images/logos/american-express.png',
imgWidth: '36px',
alt: 'American Express',
cardName: 'American Express',
cardType: 'Credit Card'
},
{
image: '/images/logos/mastercard.png',
imgWidth: '30px',
alt: 'Mastercard',
cardName: 'Mastercard',
cardType: 'Credit Card'
},
{
image: '/images/logos/jcb.png',
imgWidth: '21.4px',
alt: 'JCB',
cardName: 'JCB',
cardType: 'Credit Card'
},
{
image: '/images/logos/dinners-club.png',
imgWidth: '20px',
alt: 'Dinners Club',
cardName: 'Dinners Club',
cardType: 'Credit Card'
}
]
const PaymentMethod = ({ open, setOpen }: PaymentMethodProps) => {
// Hooks
const { mode } = useColorScheme()
return (
<Dialog
fullWidth
open={open}
onClose={() => setOpen(false)}
maxWidth='sm'
scroll='body'
closeAfterTransition={false}
sx={{ '& .MuiDialog-paper': { overflow: 'visible' } }}
>
<DialogCloseButton onClick={() => setOpen(false)} disableRipple>
<i className='tabler-x' />
</DialogCloseButton>
<DialogTitle variant='h4' className='flex gap-2 flex-col text-center sm:pbs-16 sm:pbe-10 sm:pli-16'>
Select Payment Methods
<Typography component='span' className='flex flex-col items-center'>
Supported payment methods
</Typography>
</DialogTitle>
<DialogContent className='pbs-0 sm:pli-16 sm:pbe-20'>
<div>
{cardList?.map((card, index) => (
<div
key={index}
className='flex gap-x-4 gap-y-1 flex-col sm:flex-row items-start sm:items-center justify-between first:pbe-4 last:pbs-4 [&:not(:last-child):not(:first-child)]:plb-4 [&:not(:last-child)]:border-be'
>
<div className='flex items-center gap-4'>
<Avatar
variant='rounded'
className={classnames('is-[50px] bs-[30px]', {
'bg-white': mode === 'dark',
'bg-actionHover': mode === 'light'
})}
>
<img src={card.image} alt={card.alt} height={card.imgHeight} width={card.imgWidth} />
</Avatar>
<Typography className='font-medium' color='text.primary'>
{card.cardName}
</Typography>
</div>
<Typography className='max-sm:hidden'>{card.cardType}</Typography>
</div>
))}
</div>
</DialogContent>
</Dialog>
)
}
export default PaymentMethod
@@ -0,0 +1,252 @@
'use client'
// MUI Imports
import Avatar from '@mui/material/Avatar'
import Dialog from '@mui/material/Dialog'
import DialogContent from '@mui/material/DialogContent'
import DialogTitle from '@mui/material/DialogTitle'
import Typography from '@mui/material/Typography'
import { useColorScheme } from '@mui/material/styles'
// Third-party Imports
import classnames from 'classnames'
// Component Imports
import DialogCloseButton from '../DialogCloseButton'
type PaymentProvidersProps = {
open: boolean
setOpen: (open: boolean) => void
}
type Image = {
src: string
alt?: string
height?: string
width?: string
}
type CardList = {
images: Image[]
providerName: string
}
const cardList: CardList[] = [
{
images: [
{
src: '/images/logos/visa.png',
width: '30px'
},
{
src: '/images/logos/mastercard.png',
width: '30px'
},
{
src: '/images/logos/american-express.png',
width: '36px'
},
{
src: '/images/logos/jcb.png',
height: '16px'
},
{
src: '/images/logos/dinners-club.png',
height: '16px'
}
],
providerName: 'Adyen'
},
{
images: [
{
src: '/images/logos/visa.png',
width: '30px'
},
{
src: '/images/logos/american-express.png',
width: '36px'
},
{
src: '/images/logos/jcb.png',
height: '16px'
},
{
src: '/images/logos/dinners-club.png',
height: '16px'
}
],
providerName: '2Checkout'
},
{
images: [
{
src: '/images/logos/visa.png',
width: '30px'
},
{
src: '/images/logos/american-express.png',
width: '36px'
},
{
src: '/images/logos/mastercard.png',
width: '30px'
},
{
src: '/images/logos/jcb.png',
height: '16px'
}
],
providerName: 'Airpay'
},
{
images: [
{
src: '/images/logos/american-express.png',
width: '36px'
},
{
src: '/images/logos/jcb.png',
height: '16px'
},
{
src: '/images/logos/dinners-club.png',
height: '16px'
}
],
providerName: 'Authorize.net'
},
{
images: [
{
src: '/images/logos/mastercard.png',
width: '30px'
},
{
src: '/images/logos/american-express.png',
width: '36px'
},
{
src: '/images/logos/jcb.png',
height: '16px'
}
],
providerName: 'Bambora'
},
{
images: [
{
src: '/images/logos/visa.png',
width: '30px'
},
{
src: '/images/logos/mastercard.png',
width: '30px'
},
{
src: '/images/logos/american-express.png',
width: '36px'
},
{
src: '/images/logos/jcb.png',
height: '16px'
},
{
src: '/images/logos/dinners-club.png',
height: '16px'
}
],
providerName: 'Cayan'
},
{
images: [
{
src: '/images/logos/visa.png',
width: '30px'
},
{
src: '/images/logos/american-express.png',
width: '36px'
},
{
src: '/images/logos/jcb.png',
height: '16px'
},
{
src: '/images/logos/dinners-club.png',
height: '16px'
}
],
providerName: 'Chase Paymentech (Orbital)'
},
{
images: [
{
src: '/images/logos/visa.png',
width: '30px'
},
{
src: '/images/logos/mastercard.png',
width: '30px'
}
],
providerName: 'Checkout.com'
}
]
const PaymentProviders = ({ open, setOpen }: PaymentProvidersProps) => {
// Hooks
const { mode } = useColorScheme()
return (
<Dialog
fullWidth
open={open}
onClose={() => setOpen(false)}
maxWidth='md'
scroll='body'
closeAfterTransition={false}
sx={{ '& .MuiDialog-paper': { overflow: 'visible' } }}
>
<DialogCloseButton onClick={() => setOpen(false)} disableRipple>
<i className='tabler-x' />
</DialogCloseButton>
<DialogTitle variant='h4' className='flex gap-2 flex-col text-center sm:pbs-16 sm:pbe-10 sm:pli-16'>
Select Payment Providers
<Typography component='span' className='flex flex-col text-center'>
Third-party payment providers
</Typography>
</DialogTitle>
<DialogContent className='pbs-0 sm:pbe-20 sm:pli-16'>
<div>
{cardList?.map((card, index) => (
<div
key={index}
className='flex sm:items-center flex-col sm:flex-row items-start justify-between flex-wrap gap-x-4 gap-y-1 first:pbe-4 last:pbs-4 [&:not(:last-child):not(:first-child)]:plb-4 [&:not(:last-child)]:border-be'
>
<Typography className='font-medium' color='text.primary'>
{card.providerName}
</Typography>
<div className='flex gap-x-4 gap-y-2 flex-wrap'>
{card.images.map((image, index) => (
<Avatar
key={index}
variant='rounded'
className={classnames('is-[50px] bs-[30px]', {
'bg-white': mode === 'dark',
'bg-actionHover': mode === 'light'
})}
>
<img src={image.src} alt={image.alt} height={image.height} width={image.width} />
</Avatar>
))}
</div>
</div>
))}
</div>
</DialogContent>
</Dialog>
)
}
export default PaymentProviders
@@ -0,0 +1,105 @@
// MUI Imports
import Dialog from '@mui/material/Dialog'
import DialogTitle from '@mui/material/DialogTitle'
import DialogContent from '@mui/material/DialogContent'
import DialogActions from '@mui/material/DialogActions'
import Typography from '@mui/material/Typography'
import Button from '@mui/material/Button'
import Checkbox from '@mui/material/Checkbox'
import FormControlLabel from '@mui/material/FormControlLabel'
import Alert from '@mui/material/Alert'
import AlertTitle from '@mui/material/AlertTitle'
// Component Imports
import CustomTextField from '@core/components/mui/TextField'
import DialogCloseButton from '../DialogCloseButton'
type PermissionDialogProps = {
open: boolean
setOpen: (open: boolean) => void
data?: string
}
type EditProps = {
handleClose: () => void
data: string
}
const AddContent = ({ handleClose }: { handleClose: () => void }) => {
return (
<>
<DialogContent className='overflow-visible pbs-0 sm:pli-16'>
<CustomTextField
fullWidth
label='Permission Name'
variant='outlined'
placeholder='Enter Permission Name'
className='mbe-2'
/>
<FormControlLabel control={<Checkbox />} label='Set as core permission' />
</DialogContent>
<DialogActions className='flex max-sm:flex-col max-sm:items-center max-sm:gap-2 justify-center pbs-0 sm:pbe-16 sm:pli-16'>
<Button type='submit' variant='contained' onClick={handleClose}>
Create Permission
</Button>
<Button onClick={handleClose} variant='tonal' color='secondary' className='max-sm:mis-0'>
Discard
</Button>
</DialogActions>
</>
)
}
const EditContent = ({ handleClose, data }: EditProps) => {
return (
<DialogContent className='overflow-visible pbs-0 sm:pli-16'>
<Alert severity='warning' className='mbe-8'>
<AlertTitle>Warning!</AlertTitle>
By editing the permission name, you might break the system permissions functionality. Please ensure you&#39;re
absolutely certain before proceeding.
</Alert>
<div className='flex items-end gap-4 mbe-2'>
<CustomTextField
fullWidth
size='small'
defaultValue={data}
variant='outlined'
label='Permission Name'
placeholder='Enter Permission Name'
/>
<Button variant='contained' onClick={handleClose}>
Update
</Button>
</div>
<FormControlLabel control={<Checkbox />} label='Set as core permission' />
</DialogContent>
)
}
const PermissionDialog = ({ open, setOpen, data }: PermissionDialogProps) => {
const handleClose = () => {
setOpen(false)
}
return (
<Dialog
open={open}
onClose={handleClose}
closeAfterTransition={false}
sx={{ '& .MuiDialog-paper': { overflow: 'visible' } }}
>
<DialogCloseButton onClick={() => setOpen(false)} disableRipple>
<i className='tabler-x' />
</DialogCloseButton>
<DialogTitle variant='h4' className='flex flex-col gap-2 text-center sm:pbs-16 sm:pbe-6 sm:pli-16'>
{data ? 'Edit Permission' : 'Add New Permission'}
<Typography component='span' className='flex flex-col text-center'>
{data ? 'Edit permission as per your requirements.' : 'Permissions you may use and assign to your users.'}
</Typography>
</DialogTitle>
{data ? <EditContent handleClose={handleClose} data={data} /> : <AddContent handleClose={handleClose} />}
</Dialog>
)
}
export default PermissionDialog
+43
View File
@@ -0,0 +1,43 @@
'use client'
// MUI Imports
import Dialog from '@mui/material/Dialog'
import DialogContent from '@mui/material/DialogContent'
// Component Imports
import DialogCloseButton from '../DialogCloseButton'
// Type Imports
import type { PricingPlanType } from '@/types/pages/pricingTypes'
// Component Imports
import Pricing from '@components/pricing'
type PricingProps = {
open: boolean
setOpen: (open: boolean) => void
data: PricingPlanType[]
}
const PricingDialog = ({ open, setOpen, data }: PricingProps) => {
return (
<Dialog
fullWidth
maxWidth='lg'
open={open}
onClose={() => setOpen(false)}
scroll='body'
closeAfterTransition={false}
sx={{ '& .MuiDialog-paper': { overflow: 'visible' } }}
>
<DialogCloseButton onClick={() => setOpen(false)} disableRipple>
<i className='tabler-x' />
</DialogCloseButton>
<DialogContent className='sm:p-16'>
<Pricing data={data} />
</DialogContent>
</Dialog>
)
}
export default PricingDialog
+161
View File
@@ -0,0 +1,161 @@
'use client'
// React Imports
import type { ReactNode } from 'react'
// MUI Imports
import Dialog from '@mui/material/Dialog'
import DialogTitle from '@mui/material/DialogTitle'
import DialogContent from '@mui/material/DialogContent'
import Typography from '@mui/material/Typography'
import Grid from '@mui/material/Grid2'
import Divider from '@mui/material/Divider'
import Button from '@mui/material/Button'
import InputAdornment from '@mui/material/InputAdornment'
// Third-party Imports
import classnames from 'classnames'
// Component Imports
import CustomIconButton from '@core/components/mui/IconButton'
import CustomTextField from '@core/components/mui/TextField'
import CustomAvatar from '@core/components/mui/Avatar'
import DialogCloseButton from '../DialogCloseButton'
import Keyboard from '@/assets/svg/Keyboard'
import Paper from '@/assets/svg/Paper'
import Rocket from '@/assets/svg/Rocket'
// Config Imports
import themeConfig from '@configs/themeConfig'
type ReferEarnProps = {
open: boolean
setOpen: (open: boolean) => void
}
type Options = {
icon?: ReactNode
title?: string
subtitle?: string
}
const options: Options[] = [
{
icon: <Paper />,
title: 'Send Invitation 👍🏻',
subtitle: 'Send your referral link to your friend'
},
{
icon: <Keyboard />,
title: 'Registration 😎',
subtitle: 'Let them register to our services'
},
{
icon: <Rocket />,
title: 'Free Trial 🎉',
subtitle: 'Your friend will get 30 days free trial'
}
]
const ReferEarn = ({ open, setOpen }: ReferEarnProps) => {
return (
<Dialog
fullWidth
open={open}
onClose={() => setOpen(false)}
maxWidth='md'
scroll='body'
closeAfterTransition={false}
sx={{ '& .MuiDialog-paper': { overflow: 'visible' } }}
>
<DialogCloseButton onClick={() => setOpen(false)} disableRipple>
<i className='tabler-x' />
</DialogCloseButton>
<DialogTitle variant='h4' className='flex gap-2 flex-col text-center sm:pbs-16 sm:pbe-12 sm:pli-16'>
Refer & Earn
<Typography component='span' className='flex flex-col text-center'>
{`Invite your friend to ${themeConfig.templateName}, if they sign up, you and your friend will get 30 days free
trial`}
</Typography>
</DialogTitle>
<DialogContent className='flex flex-col gap-6 pbs-0 sm:pli-16 sm:pbe-16'>
<Grid container spacing={6}>
{options?.map((option, index) => (
<Grid size={{ xs: 12, md: 4 }} key={index}>
<div className='flex items-center flex-col gap-4'>
<CustomAvatar
variant='rounded'
skin='light'
color='primary'
className='bs-[66px] is-[66px] sm:bs-[88px] sm:is-[88px]'
>
{typeof option.icon === 'string' ? (
<i className={classnames('text-[32px] sm:text-[40px]', option.icon)} />
) : (
option.icon
)}
</CustomAvatar>
<div className='flex flex-col gap-2 text-center'>
<Typography variant='h5'>{option.title}</Typography>
<Typography>{option.subtitle}</Typography>
</div>
</div>
</Grid>
))}
</Grid>
<Divider className='mbs-6' />
<div className='flex flex-col gap-6'>
<Typography variant='h5'>Invite your friends</Typography>
<div className='flex items-end is-full flex-wrap sm:flex-nowrap gap-4'>
<CustomTextField
fullWidth
size='small'
id='refer-email'
placeholder='johnDoe@email.com'
label=' Enter your friend&#39;s email address and invite them to join Vuexy 😍'
/>
<Button variant='contained' className='max-sm:is-full'>
Send
</Button>
</div>
</div>
<div className='flex flex-col gap-6'>
<Typography variant='h5'>Share the referral link</Typography>
<div className='flex items-end justify-center sm:justify-initial flex-wrap sm:flex-nowrap gap-4'>
<CustomTextField
fullWidth
size='small'
id='refer-social'
placeholder='http://pixinvent.link'
label='You can also copy and send it or share it on your social media. 🚀'
slotProps={{
input: {
endAdornment: (
<InputAdornment position='end'>
<Button size='small' className='capitalize !text-primary'>
Copy Link
</Button>
</InputAdornment>
)
}
}}
/>
<div className='flex items-center gap-1'>
<CustomIconButton className='rounded text-white bg-facebook'>
<i className='tabler-brand-facebook' />
</CustomIconButton>
<CustomIconButton className='rounded text-white bg-twitter'>
<i className='tabler-brand-twitter' />
</CustomIconButton>
<CustomIconButton className='rounded text-white bg-linkedin'>
<i className='tabler-brand-linkedin' />
</CustomIconButton>
</div>
</div>
</div>
</DialogContent>
</Dialog>
)
}
export default ReferEarn
@@ -0,0 +1,251 @@
'use client'
// React Imports
import { useState, useEffect } from 'react'
// MUI Imports
import Dialog from '@mui/material/Dialog'
import DialogTitle from '@mui/material/DialogTitle'
import DialogContent from '@mui/material/DialogContent'
import Typography from '@mui/material/Typography'
import Checkbox from '@mui/material/Checkbox'
import FormGroup from '@mui/material/FormGroup'
import FormControlLabel from '@mui/material/FormControlLabel'
import DialogActions from '@mui/material/DialogActions'
import Button from '@mui/material/Button'
// Component Imports
import DialogCloseButton from '../DialogCloseButton'
import CustomTextField from '@core/components/mui/TextField'
// Style Imports
import tableStyles from '@core/styles/table.module.css'
type RoleDialogProps = {
open: boolean
setOpen: (open: boolean) => void
title?: string
}
type DataType =
| string
| {
title: string
read?: boolean
write?: boolean
select?: boolean
}
const defaultData: DataType[] = [
'User Management',
'Content Management',
'Disputes Management',
'Database Management',
'Financial Management',
'Reporting',
'API Control',
'Repository Management',
'Payroll'
]
const RoleDialog = ({ open, setOpen, title }: RoleDialogProps) => {
// States
const [selectedCheckbox, setSelectedCheckbox] = useState<string[]>(
title
? [
'user-management-read',
'user-management-write',
'user-management-create',
'disputes-management-read',
'disputes-management-write',
'disputes-management-create'
]
: []
)
const [isIndeterminateCheckbox, setIsIndeterminateCheckbox] = useState<boolean>(false)
const handleClose = () => {
setOpen(false)
}
const togglePermission = (id: string) => {
const arr = selectedCheckbox
if (selectedCheckbox.includes(id)) {
arr.splice(arr.indexOf(id), 1)
setSelectedCheckbox([...arr])
} else {
arr.push(id)
setSelectedCheckbox([...arr])
}
}
const handleSelectAllCheckbox = () => {
if (isIndeterminateCheckbox) {
setSelectedCheckbox([])
} else {
defaultData.forEach(row => {
const id = (typeof row === 'string' ? row : row.title).toLowerCase().split(' ').join('-')
togglePermission(`${id}-read`)
togglePermission(`${id}-write`)
togglePermission(`${id}-create`)
})
}
}
useEffect(() => {
if (selectedCheckbox.length > 0 && selectedCheckbox.length < defaultData.length * 3) {
setIsIndeterminateCheckbox(true)
} else {
setIsIndeterminateCheckbox(false)
}
}, [selectedCheckbox])
return (
<Dialog
fullWidth
maxWidth='md'
scroll='body'
open={open}
onClose={handleClose}
closeAfterTransition={false}
sx={{ '& .MuiDialog-paper': { overflow: 'visible' } }}
>
<DialogCloseButton onClick={() => setOpen(false)} disableRipple>
<i className='tabler-x' />
</DialogCloseButton>
<DialogTitle variant='h4' className='flex flex-col gap-2 text-center sm:pbs-16 sm:pbe-6 sm:pli-16'>
{title ? 'Edit Role' : 'Add Role'}
<Typography component='span' className='flex flex-col text-center'>
Set Role Permissions
</Typography>
</DialogTitle>
<form onSubmit={e => e.preventDefault()}>
<DialogContent className='overflow-visible flex flex-col gap-6 pbs-0 sm:pli-16'>
<CustomTextField
label='Role Name'
variant='outlined'
fullWidth
placeholder='Enter Role Name'
defaultValue={title}
onChange={e => e.target.value}
/>
<Typography variant='h5' className='min-is-[225px]'>
Role Permissions
</Typography>
<div className='overflow-x-auto'>
<table className={tableStyles.table}>
<tbody>
<tr className='border-bs-0'>
<th className='pis-0'>
<Typography color='text.primary' className='font-medium whitespace-nowrap flex-grow min-is-[225px]'>
Administrator Access
</Typography>
</th>
<th className='!text-end pie-0'>
<FormControlLabel
className='mie-0 capitalize'
control={
<Checkbox
onChange={handleSelectAllCheckbox}
indeterminate={isIndeterminateCheckbox}
checked={selectedCheckbox.length === defaultData.length * 3}
/>
}
label='Select All'
/>
</th>
</tr>
{defaultData.map((item, index) => {
const id = (typeof item === 'string' ? item : item.title).toLowerCase().split(' ').join('-')
return (
<tr key={index} className='border-be'>
<td className='pis-0'>
<Typography
className='font-medium whitespace-nowrap flex-grow min-is-[225px]'
color='text.primary'
>
{typeof item === 'object' ? item.title : item}
</Typography>
</td>
<td className='!text-end pie-0'>
{typeof item === 'object' ? (
<FormGroup className='flex-row justify-end flex-nowrap gap-6'>
<FormControlLabel
className='mie-0'
control={<Checkbox checked={item.read} />}
label='Read'
/>
<FormControlLabel
className='mie-0'
control={<Checkbox checked={item.write} />}
label='Write'
/>
<FormControlLabel
className='mie-0'
control={<Checkbox checked={item.select} />}
label='Select'
/>
</FormGroup>
) : (
<FormGroup className='flex-row justify-end flex-nowrap gap-6'>
<FormControlLabel
className='mie-0'
control={
<Checkbox
id={`${id}-read`}
onChange={() => togglePermission(`${id}-read`)}
checked={selectedCheckbox.includes(`${id}-read`)}
/>
}
label='Read'
/>
<FormControlLabel
className='mie-0'
control={
<Checkbox
id={`${id}-write`}
onChange={() => togglePermission(`${id}-write`)}
checked={selectedCheckbox.includes(`${id}-write`)}
/>
}
label='Write'
/>
<FormControlLabel
className='mie-0'
control={
<Checkbox
id={`${id}-create`}
onChange={() => togglePermission(`${id}-create`)}
checked={selectedCheckbox.includes(`${id}-create`)}
/>
}
label='Create'
/>
</FormGroup>
)}
</td>
</tr>
)
})}
</tbody>
</table>
</div>
</DialogContent>
<DialogActions className='justify-center pbs-0 sm:pbe-16 sm:pli-16'>
<Button variant='contained' type='submit' onClick={handleClose}>
Submit
</Button>
<Button variant='tonal' type='reset' color='secondary' onClick={handleClose}>
Cancel
</Button>
</DialogActions>
</form>
</Dialog>
)
}
export default RoleDialog
@@ -0,0 +1,253 @@
'use client'
// React Imports
import { useState } from 'react'
import type { MouseEvent } from 'react'
// MUI Imports
import Dialog from '@mui/material/Dialog'
import DialogTitle from '@mui/material/DialogTitle'
import DialogContent from '@mui/material/DialogContent'
import Button from '@mui/material/Button'
import IconButton from '@mui/material/IconButton'
import Typography from '@mui/material/Typography'
import Avatar from '@mui/material/Avatar'
import List from '@mui/material/List'
import ListItem from '@mui/material/ListItem'
import ListItemAvatar from '@mui/material/ListItemAvatar'
import ListItemText from '@mui/material/ListItemText'
import Menu from '@mui/material/Menu'
import MenuItem from '@mui/material/MenuItem'
// Component Imports
import DialogCloseButton from '../DialogCloseButton'
import CustomAutocomplete from '@core/components/mui/Autocomplete'
import CustomTextField from '@core/components/mui/TextField'
import CustomAvatar from '@core/components/mui/Avatar'
// Config Imports
import themeConfig from '@configs/themeConfig'
type ShareProjectProps = {
open: boolean
setOpen: (open: boolean) => void
}
type OptionsType = {
avatar: string
name: string
}
type DataType = {
avatar: string
value: string
name: string
email: string
}
const data: DataType[] = [
{
avatar: '1.png',
value: 'Can Edit',
name: 'Lester Palmer',
email: 'lester.palmer@gmail.com'
},
{
avatar: '2.png',
value: 'Owner',
name: 'Mittie Blair',
email: 'mittie.blair@gmail.com'
},
{
avatar: '3.png',
value: 'Can Comment',
name: 'Marvin Wheeler',
email: 'marvin.wheeler@gmail.com'
},
{
avatar: '4.png',
value: 'Can View',
name: 'Nannie Ford',
email: 'nannie.ford@gmail.com'
},
{
avatar: '5.png',
value: 'Can Edit',
name: 'Julian Murphy',
email: 'julian.murphy@gmail.com'
},
{
avatar: '6.png',
value: 'Can View',
name: 'Sophie Gilbert',
email: 'sophie.gilbert@gmail.com'
},
{
avatar: '7.png',
value: 'Can Comment',
name: 'Chris Watkins',
email: 'chris.watkins@gmail.com'
},
{
avatar: '8.png',
value: 'Can Edit',
name: 'Adelaide Nichols',
email: 'adelaide.nichols@gmail.com'
}
]
const autocompleteOptions: OptionsType[] = [
{
avatar: '1.png',
name: 'Chandler Bing'
},
{
avatar: '2.png',
name: 'Rachel Green'
},
{
avatar: '3.png',
name: 'Joey Tribbiani'
},
{
avatar: '4.png',
name: 'Pheobe Buffay'
},
{
avatar: '5.png',
name: 'Ross Geller'
},
{
avatar: '8.png',
name: 'Monica Geller'
}
]
const ShareProject = ({ open, setOpen }: ShareProjectProps) => {
// States
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)
const handleClick = (event: MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget)
}
const handleClose = () => {
setAnchorEl(null)
}
return (
<Dialog
fullWidth
maxWidth='md'
scroll='body'
open={open}
onClose={() => setOpen(false)}
closeAfterTransition={false}
sx={{ '& .MuiDialog-paper': { overflow: 'visible' } }}
>
<DialogCloseButton onClick={() => setOpen(false)} disableRipple>
<i className='tabler-x' />
</DialogCloseButton>
<DialogTitle variant='h4' className='flex gap-2 flex-col text-center sm:pbs-16 sm:pbe-6 sm:pli-16'>
Share Project
<Typography component='span' className='flex flex-col text-center'>
Share project with the team members
</Typography>
</DialogTitle>
<DialogContent className='flex flex-col gap-6 pbs-0 sm:pli-16 sm:pbe-16'>
<div className='flex flex-col gap-2'>
<CustomAutocomplete
fullWidth
options={autocompleteOptions || []}
slotProps={{ listbox: { component: List } }}
id='add-member'
getOptionLabel={option => option.name}
renderInput={params => (
<CustomTextField {...params} size='small' placeholder='Add project members...' label='Add Members' />
)}
renderOption={(props, option) => {
const { key, ...rest } = props
return (
<ListItem key={key} {...rest} sx={{ width: 'calc(100% - 1rem)' }}>
<ListItemAvatar>
<CustomAvatar src={`/images/avatars/${option.avatar}`} alt={option.name} size={30} />
</ListItemAvatar>
<ListItemText primary={option.name} />
</ListItem>
)
}}
/>
</div>
<div className='flex flex-col gap-4'>
<Typography variant='h5'>{`${data.length} Members`}</Typography>
<div className='flex flex-col flex-wrap gap-4'>
{data.map((member, index) => (
<div key={index} className='flex items-center is-full gap-4'>
<Avatar src={`/images/avatars/${member.avatar}`} alt={member.name} />
<div className='flex justify-between items-center is-full overflow-hidden'>
<div className='flex flex-col items-start overflow-hidden'>
<Typography className='truncate is-full' color='text.primary'>
{member.name}
</Typography>
<Typography variant='body2' className='truncate is-full'>
{member.email}
</Typography>
</div>
<IconButton className='sm:hidden' onClick={handleClick}>
<i className='tabler-chevron-down text-base' />
</IconButton>
<Button
color='secondary'
className='hidden sm:flex'
onClick={handleClick}
endIcon={<i className='tabler-chevron-down text-base' />}
>
{member.value}
</Button>
</div>
</div>
))}
<Menu
keepMounted
anchorEl={anchorEl}
onClose={handleClose}
open={Boolean(anchorEl)}
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
transformOrigin={{ vertical: 'top', horizontal: 'right' }}
>
<MenuItem value='Owner' onClick={handleClose}>
Owner
</MenuItem>
<MenuItem value='Can Edit' onClick={handleClose}>
Can Edit
</MenuItem>
<MenuItem value='Can Comment' onClick={handleClose}>
Can Comment
</MenuItem>
<MenuItem value='Can View' onClick={handleClose}>
Can View
</MenuItem>
</Menu>
</div>
</div>
<div className='flex items-center justify-between flex-wrap gap-4'>
<div className='flex items-center flex-grow gap-2'>
<i className='tabler-users text-xl' />
<Typography
color='text.primary'
className='font-medium'
>{`Public to ${themeConfig.templateName} - Pixinvent`}</Typography>
</div>
<Button variant='contained' className='flex' startIcon={<i className='tabler-link text-base' />}>
Copy Project Link
</Button>
</div>
</DialogContent>
</Dialog>
)
}
export default ShareProject
@@ -0,0 +1,241 @@
'use client'
// React Imports
import { useState } from 'react'
import type { ChangeEvent } from 'react'
// MUI Imports
import Dialog from '@mui/material/Dialog'
import DialogTitle from '@mui/material/DialogTitle'
import DialogActions from '@mui/material/DialogActions'
import DialogContent from '@mui/material/DialogContent'
import Grid from '@mui/material/Grid2'
import Button from '@mui/material/Button'
import Typography from '@mui/material/Typography'
import Alert from '@mui/material/Alert'
import AlertTitle from '@mui/material/AlertTitle'
// Type Imports
import type { CustomInputHorizontalData } from '@core/components/custom-inputs/types'
// Component Imports
import CustomInputHorizontal from '@core/components/custom-inputs/Horizontal'
import DialogCloseButton from '../DialogCloseButton'
import CustomTextField from '@core/components/mui/TextField'
type TwoFactorAuthProps = {
open: boolean
setOpen: (open: boolean) => void
}
const data: CustomInputHorizontalData[] = [
{
title: (
<div className='flex items-top gap-1'>
<i className='tabler-settings text-xl shrink-0' />
<Typography className='font-medium' color='text.primary'>
Authenticator Apps
</Typography>
</div>
),
value: 'app',
isSelected: true,
content: 'Get code from an app like Google Authenticator or Microsoft Authenticator.'
},
{
title: (
<div className='flex items-top gap-1'>
<i className='tabler-message-2 text-xl' />
<Typography className='font-medium' color='text.primary'>
SMS
</Typography>
</div>
),
value: 'sms',
content: 'We will send a code via SMS if you need to use your backup login method.'
}
]
const SMSDialog = (handleAuthDialogClose: () => void) => {
return (
<>
<DialogTitle variant='h5' className='flex flex-col gap-2 sm:pbs-16 sm:pbe-6 sm:pli-16'>
Verify Your Mobile Number for SMS
<Typography component='span' className='flex flex-col'>
Enter your mobile phone number with country code and we will send you a verification code.
</Typography>
</DialogTitle>
<DialogContent className='overflow-visible pbs-0 sm:pbe-16 sm:pli-16'>
<CustomTextField fullWidth type='number' label='Mobile Number' placeholder='123 456 7890' />
</DialogContent>
<DialogActions className='pbs-0 sm:pbe-16 sm:pli-16'>
<Button variant='tonal' type='reset' color='secondary' onClick={handleAuthDialogClose}>
Cancel
</Button>
<Button
color='success'
variant='contained'
type='submit'
endIcon={<i className='tabler-check' />}
onClick={handleAuthDialogClose}
>
Submit
</Button>
</DialogActions>
</>
)
}
const AppDialog = (handleAuthDialogClose: () => void) => {
return (
<>
<DialogTitle variant='h4' className='text-center sm:pbs-16 sm:pbe-6 sm:pli-16'>
Add Authenticator App
</DialogTitle>
<DialogContent className='flex flex-col gap-6 pbs-0 sm:pli-16'>
<div className='flex flex-col gap-2'>
<Typography variant='h5'>Authenticator Apps</Typography>
<Typography>
Using an authenticator app like Google Authenticator, Microsoft Authenticator, Authy, or 1Password, scan the
QR code. It will generate a 6 digit code for you to enter below.
</Typography>
</div>
<div className='flex justify-center'>
<img alt='qr-code' height={150} width={150} src='/images/misc/barcode.png' />
</div>
<div className='flex flex-col gap-4'>
<Alert severity='warning' icon={false}>
<AlertTitle>ASDLKNASDA9AHS678dGhASD78AB</AlertTitle>
If you having trouble using the QR code, select manual entry on your app
</Alert>
<CustomTextField fullWidth label='Enter Authentication Code' placeholder='Enter Authentication Code' />
</div>
</DialogContent>
<DialogActions className='pbs-0 sm:pbe-16 sm:pli-16'>
<Button variant='tonal' type='reset' color='secondary' onClick={handleAuthDialogClose}>
Cancel
</Button>
<Button
color='success'
variant='contained'
type='submit'
endIcon={<i className='tabler-check' />}
onClick={handleAuthDialogClose}
>
Submit
</Button>
</DialogActions>
</>
)
}
const TwoFactorAuth = ({ open, setOpen }: TwoFactorAuthProps) => {
// Vars
const initialSelectedOption: string = data.filter(item => item.isSelected)[
data.filter(item => item.isSelected).length - 1
].value
// States
const [authType, setAuthType] = useState<string>(initialSelectedOption)
const [showAuthDialog, setShowAuthDialog] = useState<boolean>(false)
const handleClose = () => {
setOpen(false)
if (authType !== 'app') {
setAuthType('app')
}
}
const handleAuthDialogClose = () => {
setShowAuthDialog(false)
setShowAuthDialog(false)
if (authType !== 'app') {
setTimeout(() => {
setAuthType('app')
}, 250)
}
}
const handleOptionChange = (prop: string | ChangeEvent<HTMLInputElement>) => {
if (typeof prop === 'string') {
setAuthType(prop)
} else {
setAuthType((prop.target as HTMLInputElement).value)
}
}
return (
<>
<Dialog
fullWidth
maxWidth='md'
scroll='body'
open={open}
onClose={() => setOpen(false)}
closeAfterTransition={false}
sx={{ '& .MuiDialog-paper': { overflow: 'visible' } }}
>
<DialogCloseButton onClick={handleClose} disableRipple>
<i className='tabler-x' />
</DialogCloseButton>
<DialogTitle variant='h4' className='flex gap-2 flex-col text-center sm:pbs-16 sm:pbe-6 sm:pli-16'>
Select Authentication Method
<Typography component='span' className='flex flex-col text-center'>
You also need to select a method by which the proxy authenticates to the directory serve.
</Typography>
</DialogTitle>
<DialogContent className='pbs-0 sm:pli-16'>
<Grid container spacing={6}>
{data.map((item, index) => (
<CustomInputHorizontal
type='radio'
key={index}
selected={authType}
handleChange={handleOptionChange}
data={item}
gridProps={{ size: { xs: 12 } }}
name='auth-method'
/>
))}
</Grid>
</DialogContent>
<DialogActions className='pbs-0 sm:pbe-16 sm:pli-16 flex justify-center'>
<Button
variant='contained'
onClick={() => {
setOpen(false)
setShowAuthDialog(true)
}}
className='capitalize'
>
Continue
</Button>
<Button variant='tonal' color='secondary' onClick={handleClose} className='capitalize'>
Cancel
</Button>
</DialogActions>
</Dialog>
<Dialog
fullWidth
maxWidth='md'
scroll='body'
open={showAuthDialog}
onClose={handleAuthDialogClose}
closeAfterTransition={false}
sx={{ '& .MuiDialog-paper': { overflow: 'visible' } }}
>
<DialogCloseButton onClick={handleAuthDialogClose} disableRipple>
<i className='tabler-x' />
</DialogCloseButton>
<form onSubmit={e => e.preventDefault()}>
{authType === 'sms' ? SMSDialog(handleAuthDialogClose) : AppDialog(handleAuthDialogClose)}
</form>
</Dialog>
</>
)
}
export default TwoFactorAuth
@@ -0,0 +1,92 @@
'use client'
// React Imports
import { useState } from 'react'
// MUI Imports
import Dialog from '@mui/material/Dialog'
import DialogTitle from '@mui/material/DialogTitle'
import DialogContent from '@mui/material/DialogContent'
import Button from '@mui/material/Button'
import Typography from '@mui/material/Typography'
import MenuItem from '@mui/material/MenuItem'
import Divider from '@mui/material/Divider'
// Style Imports
import ConfirmationDialog from '../confirmation-dialog'
//Component Imports
import CustomTextField from '@core/components/mui/TextField'
import DialogCloseButton from '../DialogCloseButton'
type UpgradePlanProps = {
open: boolean
setOpen: (open: boolean) => void
}
const UpgradePlan = ({ open, setOpen }: UpgradePlanProps) => {
// States
const [openConfirmation, setOpenConfirmation] = useState(false)
const handleClose = () => {
setOpen(false)
}
return (
<>
<Dialog
fullWidth
open={open}
onClose={handleClose}
closeAfterTransition={false}
sx={{ '& .MuiDialog-paper': { overflow: 'visible' } }}
>
<DialogCloseButton onClick={() => setOpen(false)} disableRipple>
<i className='tabler-x' />
</DialogCloseButton>
<DialogTitle variant='h4' className='flex flex-col gap-2 text-center sm:pbs-16 sm:pbe-6 sm:pli-16'>
Upgrade Plan
<Typography component='span' className='flex flex-col text-center'>
Choose the best plan for user
</Typography>
</DialogTitle>
<DialogContent className='overflow-visible pbs-0 sm:pli-16 sm:pbe-16'>
<div className='flex items-end gap-4 flex-col sm:flex-row'>
<CustomTextField select fullWidth label='Choose Plan' defaultValue='Standard' id='user-view-plans-select'>
<MenuItem value='Basic'>Basic - $0/month</MenuItem>
<MenuItem value='Standard'>Standard - $99/month</MenuItem>
<MenuItem value='Enterprise'>Enterprise - $499/month</MenuItem>
<MenuItem value='Company'>Company - $999/month</MenuItem>
</CustomTextField>
<Button variant='contained' className='capitalize max-sm:is-full'>
Upgrade
</Button>
</div>
<Divider className='mlb-6' />
<div className='flex flex-col gap-1'>
<Typography variant='body2'>User current plan is standard plan</Typography>
<div className='flex items-center justify-between flex-wrap gap-2'>
<div className='flex justify-center items-baseline gap-1'>
<Typography component='sup' className='self-start mbs-3' color='primary.main'>
$
</Typography>
<Typography component='span' color='primary.main' variant='h1'>
99
</Typography>
<Typography variant='body2' component='sub' className='self-baseline'>
/month
</Typography>
</div>
<Button variant='tonal' className='capitalize' color='error' onClick={() => setOpenConfirmation(true)}>
Cancel Subscription
</Button>
</div>
</div>
</DialogContent>
</Dialog>
<ConfirmationDialog open={openConfirmation} setOpen={setOpenConfirmation} type='unsubscribe' />
</>
)
}
export default UpgradePlan