Compare commits

..

7 Commits

45 changed files with 13069 additions and 533 deletions

1010
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -147,6 +147,10 @@
"harmonyClub": {
"title": "Harmony Club",
"description": "Encourage repeat purchases by sending discount codes and points to your customers."
},
"harmonyBook": {
"title": "Harmony Book",
"description": "Improve customer engagement and smooth the path to growth and development of your business by making the scheduling process smarter."
}
}
}

View File

@@ -147,6 +147,10 @@
"harmonyClub": {
"title": "هارمونی کلاب",
"description": "با ارسال کد تخفیف و امتیاز به مشتریان کسب و کارتان آنها را به خرید مجدد ترغیب کنید"
},
"harmonyBook": {
"title": "هارمونی بوک",
"description": "با هوشمندسازی فرایند نوبت‌دهی، تعامل با مشتری را بهبود بخشیده و مسیر رشد و توسعه کسب‌و‌کارتان را هموارتر کنید"
}
}
}

BIN
src/assets/book-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
src/assets/club-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 216 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 198 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 219 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 199 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 196 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 230 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 220 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +1,4 @@
import { Menu, Stack, Typography, Box, Button } from '@mui/material';
import { Menu, Stack, Typography, Box, Button, lighten } from '@mui/material';
import { blue } from '@mui/material/colors';
import { Icon } from '@harmony/kit';
import { ArrowLeft, ArrowRight } from 'iconsax-react';
@@ -43,15 +43,13 @@ export default function ProductsMenu({
},
}}
>
{/* 1. Header Link */}
<Box sx={{ px: 2, py: 1, bgcolor: blue[50] }}>
<Typography variant="body2" color="primary.main">
{t('products.menu.title')}
</Typography>
</Box>
<Box sx={{ px: 2, py: 1 }}>
{/* 2. Map through products to create MenuItems */}
<Stack sx={{ px: 2, py: 1 }} spacing={1}>
{productsData.map((product) => (
<Stack
key={product.id}
@@ -60,7 +58,6 @@ export default function ProductsMenu({
alignItems="center"
width="100%"
>
{/* Text Content */}
<Stack minWidth={0} direction="column" spacing={0.5} flexGrow={1}>
<Typography variant="h6">{t(product.titleKey)}</Typography>
<Typography variant="body2" color="text.secondary">
@@ -71,7 +68,6 @@ export default function ProductsMenu({
href={product.demoLink}
target="_blank"
variant="text"
color="club"
endIcon={
<Icon
Component={i18n.dir() === 'ltr' ? ArrowRight : ArrowLeft}
@@ -80,6 +76,11 @@ export default function ProductsMenu({
sx={{
alignSelf: 'flex-start',
width: 'unset',
color: product.color,
':hover': {
bgcolor: lighten(product.color, 0.9),
},
}}
>
{t('products.menu.getDemo')}
@@ -89,7 +90,7 @@ export default function ProductsMenu({
<Box sx={{ width: 69 }}>{product.LogoComponent}</Box>
</Stack>
))}
</Box>
</Stack>
</Menu>
);
}

View File

@@ -1,5 +1,7 @@
import Logo from '@/components/Logo';
import { Box } from '@mui/material';
import type { ReactElement } from 'react';
import ClubLogo from '@/assets/club-logo.png';
import BookLogo from '@/assets/book-logo.png';
export interface Product {
id: string;
@@ -7,6 +9,7 @@ export interface Product {
descriptionKey: string;
LogoComponent: ReactElement;
demoLink: string;
color: string;
}
export const productsData: Product[] = [
@@ -14,8 +17,29 @@ export const productsData: Product[] = [
id: 'harmony-club',
titleKey: 'products.harmonyClub.title',
descriptionKey: 'products.harmonyClub.description',
LogoComponent: <Logo isIcon boxSx={{ width: 69, height: 55 }} />, // Reference the component
demoLink: 'https://club.business-harmony.com',
LogoComponent: (
<Box
component="img"
src={ClubLogo}
sx={{ width: 69, aspectRatio: '1 / 1', objectFit: 'contain' }}
/>
), // Reference the component
demoLink: 'https://business-harmony.com/club/',
color: '#ff5722',
},
{
id: 'harmony-book',
titleKey: 'products.harmonyBook.title',
descriptionKey: 'products.harmonyBook.description',
LogoComponent: (
<Box
component="img"
src={BookLogo}
sx={{ width: 69, aspectRatio: '1 / 1', objectFit: 'contain', px: 0.5 }}
/>
), // Reference the component
demoLink: 'https://business-harmony.com/book/',
color: '#d3365d',
},
// add more products here
];

View File

@@ -20,8 +20,8 @@ export const AuthenticationCard = ({
},
mx: 2,
boxSizing: 'border-box',
maxWidth: 636,
width: '100%',
maxWidth: 600,
...sx,
}}
>

View File

@@ -76,7 +76,9 @@ export function LoginRegisterForm({
setLoginRegisterValue(newValue);
const strippedValue = newValue.startsWith('+') ? newValue.substring(1) : newValue;
const strippedValue = newValue.startsWith('+')
? newValue.substring(1)
: newValue;
if (isNumeric(strippedValue) && strippedValue.length > 0) {
setAuthType('phone');
} else {
@@ -147,7 +149,7 @@ export function LoginRegisterForm({
newValue,
res.userStatus,
res.totalSecondForOtpToExpire,
authType
authType,
);
} else {
toast({ message: res.message, severity: 'error' });
@@ -191,7 +193,12 @@ export function LoginRegisterForm({
helperText={inputError && t(error || '')}
autoFocus
slotProps={{
htmlInput: { dir: 'auto', sx: { lineHeight: 1.5 } },
htmlInput: {
dir: 'auto',
sx: { lineHeight: 1.5 },
name: 'username',
autoComplete: 'username',
},
input: {
endAdornment: i18n.dir() === 'rtl' && (
<CountryCodeSelector

View File

@@ -84,14 +84,10 @@ export const InfoRowEdit = forwardRef(
}
label={label}
error={
name !== 'nationalCode' &&
touched[name] &&
(value.trim() === '' || !isValidName(value))
touched[name] && (value.trim() === '' || !isValidName(value))
}
helperText={
name !== 'nationalCode' &&
touched[name] &&
(value.trim() === '' || !isValidName(value))
touched[name] && (value.trim() === '' || !isValidName(value))
? t('settingForm.thisFieldIsRequired', { ns: 'setting' })
: undefined
}

View File

@@ -111,3 +111,127 @@
url('./assets/fonts/ttf/iranyekanwebextrablackfanum.ttf')
format('truetype');
}
@font-face {
font-family: iranyekanEnNum;
font-style: normal;
font-weight: bold;
src: url('./assets/fonts/eot/iranyekanwebbold.eot');
src:
url('./assets/fonts/eot/iranyekanwebbold.eot?#iefix')
format('embedded-opentype'),
/* IE6-8 */ url('./assets/fonts/woff/iranyekanwebbold.woff') format('woff'),
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
url('./assets/fonts/woff2/iranyekanwebbold.woff2') format('woff2'),
/* FF39+,Chrome36+, Opera24+*/
url('./assets/fonts/ttf/iranyekanwebbold.ttf') format('truetype');
}
@font-face {
font-family: iranyekanEnNum;
font-style: normal;
font-weight: 100;
src: url('./assets/fonts/eot/iranyekanwebthin.eot');
src:
url('./assets/fonts/eot/iranyekanwebthin.eot?#iefix')
format('embedded-opentype'),
/* IE6-8 */ url('./assets/fonts/woff/iranyekanwebthin.woff') format('woff'),
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
url('./assets/fonts/woff2/iranyekanwebthin.woff2') format('woff2'),
/* FF39+,Chrome36+, Opera24+*/
url('./assets/fonts/ttf/iranyekanwebthin.ttf') format('truetype');
}
@font-face {
font-family: iranyekanEnNum;
font-style: normal;
font-weight: 300;
src: url('./assets/fonts/eot/iranyekanweblight.eot');
src:
url('./assets/fonts/eot/iranyekanweblight.eot?#iefix')
format('embedded-opentype'),
/* IE6-8 */ url('./assets/fonts/woff/iranyekanweblight.woff') format('woff'),
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
url('./assets/fonts/woff2/iranyekanweblight.woff2') format('woff2'),
/* FF39+,Chrome36+, Opera24+*/
url('./assets/fonts/ttf/iranyekanweblight.ttf') format('truetype');
}
@font-face {
font-family: iranyekanEnNum;
font-style: normal;
font-weight: normal;
src: url('./assets/fonts/eot/iranyekanwebregular.eot');
src:
url('./assets/fonts/eot/iranyekanwebregular.eot?#iefix')
format('embedded-opentype'),
/* IE6-8 */ url('./assets/fonts/woff/iranyekanwebregular.woff')
format('woff'),
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
url('./assets/fonts/woff2/iranyekanwebregular.woff2') format('woff2'),
/* FF39+,Chrome36+, Opera24+*/
url('./assets/fonts/ttf/iranyekanwebregular.ttf') format('truetype');
}
@font-face {
font-family: iranyekanEnNum;
font-style: normal;
font-weight: 500;
src: url('./assets/fonts/eot/iranyekanwebmedium.eot');
src:
url('./assets/fonts/eot/iranyekanwebmedium.eot?#iefix')
format('embedded-opentype'),
/* IE6-8 */ url('./assets/fonts/woff/iranyekanwebmedium.woff')
format('woff'),
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
url('./assets/fonts/woff2/iranyekanwebmedium.woff2') format('woff2'),
/* FF39+,Chrome36+, Opera24+*/
url('./assets/fonts/ttf/iranyekanwebmedium.ttf') format('truetype');
}
@font-face {
font-family: iranyekanEnNum;
font-style: normal;
font-weight: 800;
src: url('./assets/fonts/eot/iranyekanwebextrabold.eot');
src:
url('./assets/fonts/eot/iranyekanwebextrabold.eot?#iefix')
format('embedded-opentype'),
/* IE6-8 */ url('./assets/fonts/woff/iranyekanwebextrabold.woff')
format('woff'),
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
url('./assets/fonts/woff2/iranyekanwebextrabold.woff2') format('woff2'),
/* FF39+,Chrome36+, Opera24+*/
url('./assets/fonts/ttf/iranyekanwebextrabold.ttf') format('truetype');
}
@font-face {
font-family: iranyekanEnNum;
font-style: normal;
font-weight: 850;
src: url('./assets/fonts/eot/iranyekanwebblack.eot');
src:
url('./assets/fonts/eot/iranyekanwebblack.eot?#iefix')
format('embedded-opentype'),
/* IE6-8 */ url('./assets/fonts/woff/iranyekanwebblack.woff') format('woff'),
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
url('./assets/fonts/woff2/iranyekanwebblack.woff2') format('woff2'),
/* FF39+,Chrome36+, Opera24+*/
url('./assets/fonts/ttf/iranyekanwebblack.ttf') format('truetype');
}
@font-face {
font-family: iranyekanEnNum;
font-style: normal;
font-weight: 900;
src: url('./assets/fonts/eot/iranyekanwebextrablack.eot');
src:
url('./assets/fonts/eot/iranyekanwebextrablack.eot?#iefix')
format('embedded-opentype'),
/* IE6-8 */ url('./assets/fonts/woff/iranyekanwebextrablack.woff')
format('woff'),
/* FF3.6+, IE9, Chrome6+, Saf5.1+*/
url('./assets/fonts/woff2/iranyekanwebextrablack.woff2') format('woff2'),
/* FF39+,Chrome36+, Opera24+*/
url('./assets/fonts/ttf/iranyekanwebextrablack.ttf') format('truetype');
}

View File

@@ -11,6 +11,8 @@ export const CustomThemeProvider: React.FC<{ children: React.ReactNode }> = ({
const theme = useMemo(() => {
const direction = i18n.dir(i18n.language);
const isEnglish = i18n.language?.startsWith('en');
const fontFamily = isEnglish ? 'iranyekanEnNum' : 'iranyekan';
return createTheme({
direction: direction,
@@ -29,7 +31,10 @@ export const CustomThemeProvider: React.FC<{ children: React.ReactNode }> = ({
shape: {
borderRadius: 8,
},
typography: typography,
typography: {
fontFamily: [fontFamily, 'sans-serif'].join(','),
...typography,
},
components: {
MuiButton: {
defaultProps: {
@@ -59,7 +64,7 @@ export const CustomThemeProvider: React.FC<{ children: React.ReactNode }> = ({
},
},
});
}, [i18n]);
}, [i18n, i18n.language]);
return (
<ThemeProvider theme={theme} defaultMode="light">

View File

@@ -1,6 +1,5 @@
// No need for a function, just a static object
export const typography = {
fontFamily: ['iranyekan', 'sans-serif'].join(','),
fontWeightRegular: 400,
fontWeightMedium: 500,
fontWeightBold: 700,