한글화중

This commit is contained in:
익희 김 2024-12-05 22:06:19 +09:00
parent a783d387a6
commit b9056611c4
11 changed files with 82 additions and 188 deletions

View File

@ -5,6 +5,7 @@ import GuestGuard from 'src/guards/guest';
import { Card, Stack, Container, Typography } from '@mui/material'; import { Card, Stack, Container, Typography } from '@mui/material';
// components // components
import LoginMain from 'src/components/_main/auth/login'; import LoginMain from 'src/components/_main/auth/login';
import { lang } from 'src/components/lang/kr';
// Meta information // Meta information
export const metadata = { export const metadata = {
@ -33,10 +34,7 @@ export default async function Login() {
> >
<Stack mb={5}> <Stack mb={5}>
<Typography textAlign="center" variant="h4" component="h1" gutterBottom> <Typography textAlign="center" variant="h4" component="h1" gutterBottom>
Login {lang.login}
</Typography>
<Typography textAlign="center" color="text.secondary">
Login to your account to continue
</Typography> </Typography>
</Stack> </Stack>

View File

@ -4,16 +4,16 @@ import GuestGuard from 'src/guards/guest';
import { Card, Container, Typography } from '@mui/material'; import { Card, Container, Typography } from '@mui/material';
// components // components
import RegisterMain from 'src/components/_main/auth/register'; import RegisterMain from 'src/components/_main/auth/register';
import { lang } from 'src/components/lang/kr';
// Meta information // Meta information
export const metadata = { // export const metadata = {
title: 'Create Your Nextall Account | Join Us for Exclusive Deals and Seamless Shopping', // title: 'Create Your Nextall Account | Join Us for Exclusive Deals and Seamless Shopping',
description: // description:
'Register with Nextall today to unlock a world of exclusive deals, personalized recommendations, and secure transactions. Join our community for a seamless shopping experience. Sign up now and elevate your online shopping journey!', // 'Register with Nextall today to unlock a world of exclusive deals, personalized recommendations, and secure transactions. Join our community for a seamless shopping experience. Sign up now and elevate your online shopping journey!',
applicationName: 'Nextall', // applicationName: 'Nextall',
authors: 'Nextall', // authors: 'Nextall',
keywords: 'ecommerce, Nextall, Commerce, Register Nextall, RegisterFrom Nextall' // keywords: 'ecommerce, Nextall, Commerce, Register Nextall, RegisterFrom Nextall'
}; // };
export default async function Register() { export default async function Register() {
return ( return (
@ -31,10 +31,7 @@ export default async function Register() {
}} }}
> >
<Typography variant="h4" component="h1" gutterBottom textAlign="center"> <Typography variant="h4" component="h1" gutterBottom textAlign="center">
Sign up {lang['Create your account']}
</Typography>
<Typography color="text.secondary" mb={5} textAlign="center">
Create your account
</Typography> </Typography>
<RegisterMain /> <RegisterMain />
</Card> </Card>

View File

@ -2,7 +2,7 @@
import { Box, Container } from '@mui/material'; import { Box, Container } from '@mui/material';
// components // components
import HeaderBreadcrumbs from 'src/components/headerBreadcrumbs'; // import HeaderBreadcrumbs from 'src/components/headerBreadcrumbs';
import ProductList from 'src/components/_main/products'; import ProductList from 'src/components/_main/products';
export default async function Listing() { export default async function Listing() {
@ -10,7 +10,7 @@ export default async function Listing() {
<Box> <Box>
<Box sx={{ bgcolor: 'background.default' }}> <Box sx={{ bgcolor: 'background.default' }}>
<Container maxWidth="xl"> <Container maxWidth="xl">
<HeaderBreadcrumbs {/* <HeaderBreadcrumbs
heading="Products" heading="Products"
links={[ links={[
{ {
@ -21,7 +21,7 @@ export default async function Listing() {
name: 'Products' name: 'Products'
} }
]} ]}
/> /> */}
<ProductList /> <ProductList />
</Container> </Container>

View File

@ -12,6 +12,7 @@ import { useQuery } from 'react-query';
import ProductsCarousel from 'src/components/carousels/gridSlider'; import ProductsCarousel from 'src/components/carousels/gridSlider';
// icons // icons
import { IoIosArrowForward } from 'react-icons/io'; import { IoIosArrowForward } from 'react-icons/io';
import { lang } from 'src/components/lang/kr';
export default function Index() { export default function Index() {
const { data, isLoading } = useQuery(['featured-products'], () => api.getFeaturedProducts()); const { data, isLoading } = useQuery(['featured-products'], () => api.getFeaturedProducts());
@ -25,7 +26,7 @@ export default function Index() {
> >
<Box> <Box>
<Typography variant="h2" color="text.primary" mt={{ xs: 4, md: 8 }}> <Typography variant="h2" color="text.primary" mt={{ xs: 4, md: 8 }}>
상품 {lang['Products']}
</Typography> </Typography>
</Box> </Box>
<Button <Button
@ -42,13 +43,13 @@ export default function Index() {
component={NextLink} component={NextLink}
href={`/products?featured=true`} href={`/products?featured=true`}
> >
View More {lang['View More']}
</Button> </Button>
</Stack> </Stack>
{!isLoading && !Boolean(data?.data.length) ? ( {!isLoading && !Boolean(data?.data.length) ? (
<Typography variant="h3" color="error.main" textAlign="center"> <Typography variant="h3" color="error.main" textAlign="center">
Products not found {lang['Products not found']}
</Typography> </Typography>
) : ( ) : (
<ProductsCarousel data={data?.data || []} isLoading={isLoading} /> <ProductsCarousel data={data?.data || []} isLoading={isLoading} />
@ -65,9 +66,10 @@ export default function Index() {
}} }}
endIcon={<IoIosArrowForward />} endIcon={<IoIosArrowForward />}
component={NextLink} component={NextLink}
href={`/categories`} // href={`/categories`}
href={`/products?featured=true`}
> >
View More {lang['View More']}
</Button> </Button>
</Box> </Box>
); );

View File

@ -10,6 +10,7 @@ import { Typography, Grid, Box, Stack, Paper, Button } from '@mui/material';
import { IoIosArrowForward } from 'react-icons/io'; import { IoIosArrowForward } from 'react-icons/io';
// component // component
import ShopCard from 'src/components/cards/shop'; import ShopCard from 'src/components/cards/shop';
import { lang } from 'src/components/lang/kr';
export default function ShopComponent() { export default function ShopComponent() {
const { shops = [], isLoading } = useSelector(({ shops }) => shops); const { shops = [], isLoading } = useSelector(({ shops }) => shops);
@ -24,11 +25,8 @@ export default function ShopComponent() {
mb={3} mb={3}
> >
<Box width="100%"> <Box width="100%">
<Typography variant="h2" color="text.primary" mt={{ xs: 4, md: 8 }}> <Typography variant="h2" color="text.primary" mt={{ xs: 4, md: 8 }} textAlign="left">
Best Shops {lang['Best Shops']}
</Typography>
<Typography variant="body1" color="text.secondary" mb={{ xs: 3, md: 5 }}>
Our Highest Rated Shops Where You Can Find What You Are Looking For
</Typography> </Typography>
</Box> </Box>
<Button <Button
@ -45,7 +43,7 @@ export default function ShopComponent() {
component={NextLink} component={NextLink}
href={`/shops`} href={`/shops`}
> >
View More {lang['View More']}
</Button> </Button>
</Stack> </Stack>
@ -79,7 +77,7 @@ export default function ShopComponent() {
component={NextLink} component={NextLink}
href={`/shops`} href={`/shops`}
> >
View More {lang['View More']}
</Button> </Button>
</Box> </Box>
</Paper> </Paper>

View File

@ -11,6 +11,7 @@ import { useQuery } from 'react-query';
import ProductsCarousel from 'src/components/carousels/gridSlider'; import ProductsCarousel from 'src/components/carousels/gridSlider';
// icons // icons
import { IoIosArrowForward } from 'react-icons/io'; import { IoIosArrowForward } from 'react-icons/io';
import { lang } from 'src/components/lang/kr';
export default function Index() { export default function Index() {
const { data, isLoading } = useQuery(['get-top-products'], () => api.getTopRatedProducts()); const { data, isLoading } = useQuery(['get-top-products'], () => api.getTopRatedProducts());
@ -44,12 +45,12 @@ export default function Index() {
component={NextLink} component={NextLink}
href={`/products?top=1`} href={`/products?top=1`}
> >
View More {lang['View More']}
</Button> </Button>
</Stack> </Stack>
{!isLoading && !Boolean(data?.data.length) ? ( {!isLoading && !Boolean(data?.data.length) ? (
<Typography variant="h3" color="error.main" textAlign="center"> <Typography variant="h3" color="error.main" textAlign="center">
Products not found {lang['Products not found']}
</Typography> </Typography>
) : ( ) : (
<ProductsCarousel data={data?.data || []} isLoading={isLoading} /> <ProductsCarousel data={data?.data || []} isLoading={isLoading} />
@ -68,7 +69,7 @@ export default function Index() {
component={NextLink} component={NextLink}
href={`/products?top=1`} href={`/products?top=1`}
> >
View More {lang['View More']}
</Button> </Button>
</Box> </Box>
); );

View File

@ -66,7 +66,7 @@ export default function ProductListing({ category, subCategory, shop, compaign }
const isMobile = useMediaQuery('(max-width:900px)'); const isMobile = useMediaQuery('(max-width:900px)');
return ( return (
<> <>
<SortBar {/* <SortBar
sortData={sortData} sortData={sortData}
productData={data} productData={data}
category={subCategory?.parentCategory || category} category={subCategory?.parentCategory || category}
@ -74,7 +74,7 @@ export default function ProductListing({ category, subCategory, shop, compaign }
subCategory={subCategory} subCategory={subCategory}
isLoading={isLoading} isLoading={isLoading}
compaign={compaign} compaign={compaign}
/> /> */}
<ProductList data={data} isLoading={isLoading} isMobile={isMobile} /> <ProductList data={data} isLoading={isLoading} isMobile={isMobile} />
<Pagination data={data} /> <Pagination data={data} />
</> </>

View File

@ -6,7 +6,7 @@ import RouterLink from 'next/link';
import { useSearchParams } from 'next/navigation'; import { useSearchParams } from 'next/navigation';
import { useRouter } from 'next-nprogress-bar'; import { useRouter } from 'next-nprogress-bar';
import toast from 'react-hot-toast'; import toast from 'react-hot-toast';
import { lang } from '../lang/kr';
// formik // formik
import { useFormik, Form, FormikProvider } from 'formik'; import { useFormik, Form, FormikProvider } from 'formik';
// cookies // cookies
@ -26,10 +26,7 @@ import {
TextField, TextField,
IconButton, IconButton,
InputAdornment, InputAdornment,
FormControlLabel, FormControlLabel
Button,
Alert,
AlertTitle
} from '@mui/material'; } from '@mui/material';
import { LoadingButton } from '@mui/lab'; import { LoadingButton } from '@mui/lab';
// icons // icons
@ -49,7 +46,7 @@ export default function LoginForm() {
dispatch(setWishlist(data.user.wishlist)); dispatch(setWishlist(data.user.wishlist));
await createCookies('token', data.token); await createCookies('token', data.token);
setloading(false); setloading(false);
toast.success('Logged in successfully!'); toast.success(lang['Logged in successfully!']);
const isAdmin = data.user.role.includes('admin'); const isAdmin = data.user.role.includes('admin');
const isVendor = data.user.role.includes('vendor'); const isVendor = data.user.role.includes('vendor');
push(redirect || isAdmin ? '/admin/dashboard' : isVendor ? '/vendor/dashboard' : '/'); push(redirect || isAdmin ? '/admin/dashboard' : isVendor ? '/vendor/dashboard' : '/');
@ -60,8 +57,10 @@ export default function LoginForm() {
} }
}); });
const LoginSchema = Yup.object().shape({ const LoginSchema = Yup.object().shape({
email: Yup.string().email('Enter valid email').required('Email is required.'), email: Yup.string().email(lang['Enter valid email']).required(lang['Email is required']),
password: Yup.string().required('Password is required.').min(8, 'Password should be 8 characters or longer.') password: Yup.string()
.required(lang['Password is required'])
.min(8, lang['Password should be 8 characters or longer'])
}); });
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
@ -77,62 +76,15 @@ export default function LoginForm() {
mutate({ email, password }); mutate({ email, password });
} }
}); });
const { errors, touched, setFieldValue, values, handleSubmit, getFieldProps } = formik; const { errors, touched, values, handleSubmit, getFieldProps } = formik;
return ( return (
<> <>
<Stack
mb={3}
gap={2}
sx={{
'& .MuiAlert-action': {
alignItems: 'center'
}
}}
>
<Alert
severity="primary"
action={
<Button
color="inherit"
size="small"
onClick={() => {
setFieldValue('email', 'admin@nextall.com');
setFieldValue('password', 'test1234');
}}
>
Copy
</Button>
}
>
<AlertTitle>Admin</AlertTitle>
<b>Email:</b> admin@test.com | <b>password:</b> test1234
</Alert>
<Alert
severity="secondary"
action={
<Button
color="inherit"
size="small"
onClick={() => {
setFieldValue('email', 'vendor@nextall.com');
setFieldValue('password', 'test1234');
}}
>
Copy
</Button>
}
>
<AlertTitle>Vendor</AlertTitle>
<b>Email:</b> vendor@test.com | <b>password:</b> test1234
</Alert>
</Stack>
<FormikProvider value={formik}> <FormikProvider value={formik}>
<Form autoComplete="off" noValidate onSubmit={handleSubmit}> <Form autoComplete="off" noValidate onSubmit={handleSubmit}>
<Stack spacing={3}> <Stack spacing={3}>
<Stack gap={0.5} width={1}> <Stack gap={0.5} width={1}>
<Typography variant="overline" color="text.primary" htmlFor="email" component={'label'}> <Typography variant="overline" color="text.primary" htmlFor="email" component={'label'}>
Email {lang.Email}
</Typography> </Typography>
<TextField <TextField
id="email" id="email"
@ -154,7 +106,7 @@ export default function LoginForm() {
<Stack gap={0.5} width={1}> <Stack gap={0.5} width={1}>
<Typography variant="overline" color="text.primary" htmlFor="password" component={'label'}> <Typography variant="overline" color="text.primary" htmlFor="password" component={'label'}>
Password {lang.Password}
</Typography> </Typography>
<TextField <TextField
id="password" id="password"
@ -184,19 +136,18 @@ export default function LoginForm() {
<Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ my: 2 }}> <Stack direction="row" alignItems="center" justifyContent="space-between" sx={{ my: 2 }}>
<FormControlLabel <FormControlLabel
control={<Checkbox {...getFieldProps('remember')} checked={values.remember} />} control={<Checkbox {...getFieldProps('remember')} checked={values.remember} />}
label="Remember me" label={lang['Remember me']}
/> />
<Link component={RouterLink} variant="subtitle2" href="/auth/forget-password"> <Link component={RouterLink} variant="subtitle2" href="/auth/forget-password">
Forgot password {lang['Forgot password']}
</Link> </Link>
</Stack> </Stack>
<LoadingButton fullWidth size="large" type="submit" variant="contained" loading={loading}> <LoadingButton fullWidth size="large" type="submit" variant="contained" loading={loading}>
login {lang.login}
</LoadingButton> </LoadingButton>
<Typography variant="subtitle2" mt={3} textAlign="center"> <Typography variant="subtitle2" mt={3} textAlign="center">
Don{`'`}t you have an account? &nbsp;
<Link href={`/auth/register${redirect ? '?redirect=' + redirect : ''}`} component={RouterLink}> <Link href={`/auth/register${redirect ? '?redirect=' + redirect : ''}`} component={RouterLink}>
Register {lang.Register}
</Link> </Link>
</Typography> </Typography>
</Form> </Form>

View File

@ -29,6 +29,7 @@ import { MdLocalPhone } from 'react-icons/md';
import { FaTransgender } from 'react-icons/fa6'; import { FaTransgender } from 'react-icons/fa6';
// hooks // hooks
import { createCookies } from 'src/hooks/cookies'; import { createCookies } from 'src/hooks/cookies';
import { lang } from '../lang/kr';
export default function RegisterForm() { export default function RegisterForm() {
const router = useRouter(); const router = useRouter();
@ -49,8 +50,8 @@ export default function RegisterForm() {
const formik = useFormik({ const formik = useFormik({
initialValues: { initialValues: {
firstName: '', firstName: '',
lastName: '', lastName: 'test',
phone: '', phone: '01012345678',
gender: 'male', gender: 'male',
email: '', email: '',
password: '' password: ''
@ -103,84 +104,10 @@ export default function RegisterForm() {
}} }}
/> />
</Stack> </Stack>
<Stack gap={0.5} width={1}>
<Typography variant="overline" color="text.primary" htmlFor="lastName" component={'label'}>
Last Name
</Typography>
<TextField
fullWidth
id="lastName"
type="text"
{...getFieldProps('lastName')}
error={Boolean(touched.lastName && errors.lastName)}
helperText={touched.lastName && errors.lastName}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<IoPerson size={24} />
</InputAdornment>
)
}}
/>
</Stack>
</Stack>
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>
<Stack gap={0.5} width={1}>
<Typography variant="overline" color="text.primary" htmlFor="gender" component={'label'}>
Gender
</Typography>
<TextField
id="gender"
select
fullWidth
{...getFieldProps('gender')}
error={Boolean(touched.gender && errors.gender)}
helperText={touched.gender && errors.gender}
InputProps={{
startAdornment: (
<InputAdornment position="start">
{values.gender === 'male' ? (
<IoMdMale size={24} />
) : values.gender === 'female' ? (
<IoMdFemale size={24} />
) : (
<FaTransgender />
)}
</InputAdornment>
)
}}
>
{['Male', 'Female', 'Other'].map((option) => (
<MenuItem key={option} value={option.toLowerCase()}>
{option}
</MenuItem>
))}
</TextField>
</Stack>
<Stack gap={0.5} width={1}>
<Typography variant="overline" color="text.primary" htmlFor="phone" component={'label'}>
Phone
</Typography>
<TextField
fullWidth
id="phone"
type="text"
{...getFieldProps('phone')}
error={Boolean(touched.phone && errors.phone)}
helperText={touched.phone && errors.phone}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<MdLocalPhone size={24} />
</InputAdornment>
)
}}
/>
</Stack>
</Stack> </Stack>
<Stack gap={0.5} width={1}> <Stack gap={0.5} width={1}>
<Typography variant="overline" color="text.primary" htmlFor="email" component={'label'}> <Typography variant="overline" color="text.primary" htmlFor="email" component={'label'}>
Email {lang.Email}
</Typography> </Typography>
<TextField <TextField
id="email" id="email"
@ -201,7 +128,7 @@ export default function RegisterForm() {
</Stack> </Stack>
<Stack gap={0.5} width={1}> <Stack gap={0.5} width={1}>
<Typography variant="overline" color="text.primary" htmlFor="password" component={'label'}> <Typography variant="overline" color="text.primary" htmlFor="password" component={'label'}>
Password {lang.Password}
</Typography> </Typography>
<TextField <TextField
id="password" id="password"
@ -229,20 +156,19 @@ export default function RegisterForm() {
</Stack> </Stack>
<LoadingButton fullWidth size="large" type="submit" variant="contained" loading={loading}> <LoadingButton fullWidth size="large" type="submit" variant="contained" loading={loading}>
Register {lang.Register}
</LoadingButton> </LoadingButton>
</Stack> </Stack>
<Typography variant="subtitle2" mt={3} textAlign="center"> <Typography variant="subtitle2" mt={3} textAlign="center">
Already have an account? &nbsp;
<Link <Link
href={`/auth/login${router.query?.redirect ? '?redirect=' + router.query?.redirect : ''}`} href={`/auth/login${router.query?.redirect ? '?redirect=' + router.query?.redirect : ''}`}
component={RouterLink} component={RouterLink}
> >
Login {lang.login}
</Link> </Link>
</Typography> </Typography>
<Typography variant="body2" align="center" color="text.secondary" mt={2}> {/* <Typography variant="body2" align="center" color="text.secondary" mt={2}>
By registering, I agree to Nextall&nbsp; By registering, I agree to Nextall&nbsp;
<Link underline="always" color="text.primary" href="#" fontWeight={700}> <Link underline="always" color="text.primary" href="#" fontWeight={700}>
Terms Terms
@ -252,7 +178,7 @@ export default function RegisterForm() {
Privacy policy Privacy policy
</Link> </Link>
. .
</Typography> </Typography> */}
</Form> </Form>
</FormikProvider> </FormikProvider>
); );

21
src/components/lang/kr.js Normal file
View File

@ -0,0 +1,21 @@
export const lang = {
"Don't you have an account?": '가입하기',
Register: '가입',
'Forgot password': '비밀번호 찾기',
login: '로그인',
'Remember me': '아이디 저장',
Password: '비밀번호',
Email: '이메일',
'Enter valid email': '정확한 이메일을 입력해주세요',
'Email is required': '이메일은 필수 입니다',
'Password is required': '비밀번호는 필수 입니다',
'Password should be 8 characters or longer': '비밀번호는 8자 이상이 되어야 합니다',
'Logged in successfully!': '로그인 성공!',
'Create your account': '회원가입',
'First Name': '이름',
Register: '가입하기',
'Best Shops': '상점 목록',
'View More': '더보기',
'Products not found': '상품이 준비되지 않았습니다',
Products: '상품'
};

View File

@ -34,23 +34,23 @@
], ],
"mobile_menu": [ "mobile_menu": [
{ {
"name": "Home", "name": "",
"href": "/" "href": "/"
}, },
{ {
"name": "Search", "name": "검색",
"href": "/search" "href": "/search"
}, },
{ {
"name": "Product", "name": "상품",
"href": "/products" "href": "/products"
}, },
{ {
"name": "Cart", "name": "카트",
"href": "/cart" "href": "/cart"
}, },
{ {
"name": "User", "name": "사용자",
"isUser": true, "isUser": true,
"href": "/auth/login" "href": "/auth/login"
} }