Files
how2ice 005cf56baf
Some checks failed
No response / noResponse (push) Has been cancelled
CI / Continuous releases (push) Has been cancelled
CI / test-dev (macos-latest) (push) Has been cancelled
CI / test-dev (ubuntu-latest) (push) Has been cancelled
CI / test-dev (windows-latest) (push) Has been cancelled
Maintenance / main (push) Has been cancelled
Scorecards supply-chain security / Scorecards analysis (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
init project
2025-12-12 14:26:25 +09:00

324 lines
11 KiB
TypeScript

import * as React from 'react';
import Alert from '@mui/material/Alert';
import Box from '@mui/material/Box';
import MuiCard from '@mui/material/Card';
import CardActionArea from '@mui/material/CardActionArea';
import CardContent from '@mui/material/CardContent';
import Checkbox from '@mui/material/Checkbox';
import FormControl from '@mui/material/FormControl';
import FormControlLabel from '@mui/material/FormControlLabel';
import FormLabel from '@mui/material/FormLabel';
import OutlinedInput from '@mui/material/OutlinedInput';
import RadioGroup from '@mui/material/RadioGroup';
import Stack from '@mui/material/Stack';
import Typography from '@mui/material/Typography';
import { styled } from '@mui/material/styles';
import AccountBalanceRoundedIcon from '@mui/icons-material/AccountBalanceRounded';
import CreditCardRoundedIcon from '@mui/icons-material/CreditCardRounded';
import SimCardRoundedIcon from '@mui/icons-material/SimCardRounded';
import WarningRoundedIcon from '@mui/icons-material/WarningRounded';
const Card = styled(MuiCard)<{ selected?: boolean }>(({ theme }) => ({
border: '1px solid',
borderColor: (theme.vars || theme).palette.divider,
width: '100%',
'&:hover': {
background:
'linear-gradient(to bottom right, hsla(210, 100%, 97%, 0.5) 25%, hsla(210, 100%, 90%, 0.3) 100%)',
borderColor: 'primary.light',
boxShadow: '0px 2px 8px hsla(0, 0%, 0%, 0.1)',
...theme.applyStyles('dark', {
background:
'linear-gradient(to right bottom, hsla(210, 100%, 12%, 0.2) 25%, hsla(210, 100%, 16%, 0.2) 100%)',
borderColor: 'primary.dark',
boxShadow: '0px 1px 8px hsla(210, 100%, 25%, 0.5) ',
}),
},
[theme.breakpoints.up('md')]: {
flexGrow: 1,
maxWidth: `calc(50% - ${theme.spacing(1)})`,
},
variants: [
{
props: ({ selected }) => selected,
style: {
borderColor: (theme.vars || theme).palette.primary.light,
...theme.applyStyles('dark', {
borderColor: (theme.vars || theme).palette.primary.dark,
}),
},
},
],
}));
const PaymentContainer = styled('div')(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
width: '100%',
height: 375,
padding: theme.spacing(3),
borderRadius: `calc(${theme.shape.borderRadius}px + 4px)`,
border: '1px solid ',
borderColor: (theme.vars || theme).palette.divider,
background:
'linear-gradient(to bottom right, hsla(220, 35%, 97%, 0.3) 25%, hsla(220, 20%, 88%, 0.3) 100%)',
boxShadow: '0px 4px 8px hsla(210, 0%, 0%, 0.05)',
[theme.breakpoints.up('xs')]: {
height: 300,
},
[theme.breakpoints.up('sm')]: {
height: 350,
},
...theme.applyStyles('dark', {
background:
'linear-gradient(to right bottom, hsla(220, 30%, 6%, 0.2) 25%, hsla(220, 20%, 25%, 0.2) 100%)',
boxShadow: '0px 4px 8px hsl(220, 35%, 0%)',
}),
}));
const FormGrid = styled('div')(() => ({
display: 'flex',
flexDirection: 'column',
}));
export default function PaymentForm() {
const [paymentType, setPaymentType] = React.useState('creditCard');
const [cardNumber, setCardNumber] = React.useState('');
const [cvv, setCvv] = React.useState('');
const [expirationDate, setExpirationDate] = React.useState('');
const handlePaymentTypeChange = (event: {
target: { value: React.SetStateAction<string> };
}) => {
setPaymentType(event.target.value);
};
const handleCardNumberChange = (event: { target: { value: string } }) => {
const value = event.target.value.replace(/\D/g, '');
const formattedValue = value.replace(/(\d{4})(?=\d)/g, '$1 ');
if (value.length <= 16) {
setCardNumber(formattedValue);
}
};
const handleCvvChange = (event: { target: { value: string } }) => {
const value = event.target.value.replace(/\D/g, '');
if (value.length <= 3) {
setCvv(value);
}
};
const handleExpirationDateChange = (event: { target: { value: string } }) => {
const value = event.target.value.replace(/\D/g, '');
const formattedValue = value.replace(/(\d{2})(?=\d{2})/, '$1/');
if (value.length <= 4) {
setExpirationDate(formattedValue);
}
};
return (
<Stack spacing={{ xs: 3, sm: 6 }} useFlexGap>
<FormControl component="fieldset" fullWidth>
<RadioGroup
aria-label="Payment options"
name="paymentType"
value={paymentType}
onChange={handlePaymentTypeChange}
sx={{
display: 'flex',
flexDirection: { xs: 'column', sm: 'row' },
gap: 2,
}}
>
<Card selected={paymentType === 'creditCard'}>
<CardActionArea
onClick={() => setPaymentType('creditCard')}
sx={{
'.MuiCardActionArea-focusHighlight': {
backgroundColor: 'transparent',
},
'&:focus-visible': {
backgroundColor: 'action.hover',
},
}}
>
<CardContent sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<CreditCardRoundedIcon
fontSize="small"
sx={[
(theme) => ({
color: 'grey.400',
...theme.applyStyles('dark', {
color: 'grey.600',
}),
}),
paymentType === 'creditCard' && {
color: 'primary.main',
},
]}
/>
<Typography sx={{ fontWeight: 'medium' }}>Card</Typography>
</CardContent>
</CardActionArea>
</Card>
<Card selected={paymentType === 'bankTransfer'}>
<CardActionArea
onClick={() => setPaymentType('bankTransfer')}
sx={{
'.MuiCardActionArea-focusHighlight': {
backgroundColor: 'transparent',
},
'&:focus-visible': {
backgroundColor: 'action.hover',
},
}}
>
<CardContent sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<AccountBalanceRoundedIcon
fontSize="small"
sx={[
(theme) => ({
color: 'grey.400',
...theme.applyStyles('dark', {
color: 'grey.600',
}),
}),
paymentType === 'bankTransfer' && {
color: 'primary.main',
},
]}
/>
<Typography sx={{ fontWeight: 'medium' }}>Bank account</Typography>
</CardContent>
</CardActionArea>
</Card>
</RadioGroup>
</FormControl>
{paymentType === 'creditCard' && (
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
<PaymentContainer>
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
<Typography variant="subtitle2">Credit card</Typography>
<CreditCardRoundedIcon sx={{ color: 'text.secondary' }} />
</Box>
<SimCardRoundedIcon
sx={{
fontSize: { xs: 48, sm: 56 },
transform: 'rotate(90deg)',
color: 'text.secondary',
}}
/>
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
width: '100%',
gap: 2,
}}
>
<FormGrid sx={{ flexGrow: 1 }}>
<FormLabel htmlFor="card-number" required>
Card number
</FormLabel>
<OutlinedInput
id="card-number"
autoComplete="card-number"
placeholder="0000 0000 0000 0000"
required
size="small"
value={cardNumber}
onChange={handleCardNumberChange}
/>
</FormGrid>
<FormGrid sx={{ maxWidth: '20%' }}>
<FormLabel htmlFor="cvv" required>
CVV
</FormLabel>
<OutlinedInput
id="cvv"
autoComplete="CVV"
placeholder="123"
required
size="small"
value={cvv}
onChange={handleCvvChange}
/>
</FormGrid>
</Box>
<Box sx={{ display: 'flex', gap: 2 }}>
<FormGrid sx={{ flexGrow: 1 }}>
<FormLabel htmlFor="card-name" required>
Name
</FormLabel>
<OutlinedInput
id="card-name"
autoComplete="card-name"
placeholder="John Smith"
required
size="small"
/>
</FormGrid>
<FormGrid sx={{ flexGrow: 1 }}>
<FormLabel htmlFor="card-expiration" required>
Expiration date
</FormLabel>
<OutlinedInput
id="card-expiration"
autoComplete="card-expiration"
placeholder="MM/YY"
required
size="small"
value={expirationDate}
onChange={handleExpirationDateChange}
/>
</FormGrid>
</Box>
</PaymentContainer>
<FormControlLabel
control={<Checkbox name="saveCard" />}
label="Remember credit card details for next time"
/>
</Box>
)}
{paymentType === 'bankTransfer' && (
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
<Alert severity="warning" icon={<WarningRoundedIcon />}>
Your order will be processed once we receive the funds.
</Alert>
<Typography variant="subtitle1" sx={{ fontWeight: 'medium' }}>
Bank account
</Typography>
<Typography variant="body1" gutterBottom>
Please transfer the payment to the bank account details shown below.
</Typography>
<Box sx={{ display: 'flex', gap: 1 }}>
<Typography variant="body1" sx={{ color: 'text.secondary' }}>
Bank:
</Typography>
<Typography variant="body1" sx={{ fontWeight: 'medium' }}>
Mastercredit
</Typography>
</Box>
<Box sx={{ display: 'flex', gap: 1 }}>
<Typography variant="body1" sx={{ color: 'text.secondary' }}>
Account number:
</Typography>
<Typography variant="body1" sx={{ fontWeight: 'medium' }}>
123456789
</Typography>
</Box>
<Box sx={{ display: 'flex', gap: 1 }}>
<Typography variant="body1" sx={{ color: 'text.secondary' }}>
Routing number:
</Typography>
<Typography variant="body1" sx={{ fontWeight: 'medium' }}>
987654321
</Typography>
</Box>
</Box>
)}
</Stack>
);
}