Skip to content

Commit 89a0fbf

Browse files
committed
feat: enhance subscription settings and localization updates
- Improved the SubscriptionSettingsWidget by integrating SubscriptionTabs for better organization of settings. - Updated localization files for English, Persian, and Russian to include new descriptions related to Happ settings and subscription information. - Enhanced UI components across various pages for a more cohesive design, including the addition of avatars and improved layout in HappRoutingBuilder and SubscriptionSettings. - Refactored metric card components to include consistent padding and shadow effects for better visual appeal.
1 parent 4991a3a commit 89a0fbf

File tree

11 files changed

+634
-307
lines changed

11 files changed

+634
-307
lines changed

public/locales/en/remnawave.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,10 @@
559559
"serve-json-at-base-subscription": "Serve JSON at base subscription",
560560
"serve-json-description": "This will allow you to serve JSON subscriptions at the base subscription path (without /json). If the client supports it, it will be served as JSON, otherwise it will be served as usual.",
561561
"add-username-to-base-subscription": "Add #username to base subscription",
562-
"add-username-description": "Add #username to the base subscription path at the subscription route."
562+
"add-username-description": "Add #username to the base subscription path at the subscription route.",
563+
"subscription-info-description": "This settings is supprted by many clients apps such as Happ, V2RayNG, Streisand, etc.",
564+
"happ-description-line-1": "Here you can configure the Happ settings for the subscription.",
565+
"happ-description-line-2": "This settings will be used only if the subscription is used in Happ."
563566
},
564567
"page": {
565568
"component": {

public/locales/fa/remnawave.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,10 @@
559559
"serve-json-at-base-subscription": "ارائه JSON در لینک پایه پیشفرض",
560560
"serve-json-description": "درصورت پشتیبانی نرم افزار، بدون نیاز به قرار دادن /json در انتهای لینک، اشتراک JSON برای آن ارسال خواهد شد",
561561
"add-username-to-base-subscription": "افزودن #username به انتهای لینک اشتراک",
562-
"add-username-description": "با فعال کردن این گزینه #username به انتهای لینک‌های اشتراک اضافه خواهد شد."
562+
"add-username-description": "با فعال کردن این گزینه #username به انتهای لینک‌های اشتراک اضافه خواهد شد.",
563+
"happ-description-line-1": "Here you can configure the Happ settings for the subscription.",
564+
"happ-description-line-2": "This settings will be used only if the subscription is used in Happ.",
565+
"subscription-info-description": "This settings is supprted by many clients apps such as Happ, V2RayNG, Streisand, etc."
563566
},
564567
"page": {
565568
"component": {

public/locales/ru/remnawave.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,10 @@
559559
"serve-json-at-base-subscription": "Использовать JSON в базовой подписке",
560560
"serve-json-description": "Это позволит вам сервить JSON подписку в базовом пути подписки. Если запрошенный клиент поддерживает его, он будет сервиться как JSON, в противном случае он будет сервиться как обычно.",
561561
"add-username-to-base-subscription": "Добавить #username в базовую подписку",
562-
"add-username-description": "Это добавит #username в путь подписки на базовой подписке."
562+
"add-username-description": "Это добавит #username в путь подписки на базовой подписке.",
563+
"happ-description-line-1": "Here you can configure the Happ settings for the subscription.",
564+
"happ-description-line-2": "This settings will be used only if the subscription is used in Happ.",
565+
"subscription-info-description": "This settings is supprted by many clients apps such as Happ, V2RayNG, Streisand, etc."
563566
},
564567
"page": {
565568
"component": {
Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
1-
import { Paper, Stack, Text, Title } from '@mantine/core'
1+
import {
2+
Avatar,
3+
Box,
4+
Container,
5+
Group,
6+
Paper,
7+
rgba,
8+
Stack,
9+
Text,
10+
Title,
11+
useMantineTheme
12+
} from '@mantine/core'
213
import { useTranslation } from 'react-i18next'
14+
import { PiBarcode } from 'react-icons/pi'
315

416
import { SubscriptionSettingsWidget } from '@widgets/dashboard/subscription-settings/settings/subscription-settings.widget'
517
import { LoadingScreen, PageHeader } from '@shared/ui'
@@ -11,6 +23,9 @@ import { IProps } from './interfaces'
1123
export const SubscriptionSettingsPageComponent = (props: IProps) => {
1224
const { t } = useTranslation()
1325

26+
const theme = useMantineTheme()
27+
const primaryColor = theme.colors[theme.primaryColor][6]
28+
1429
const { subscriptionSettings } = props
1530

1631
if (!subscriptionSettings) {
@@ -27,25 +42,49 @@ export const SubscriptionSettingsPageComponent = (props: IProps) => {
2742
title={t('constants.subscription-settings')}
2843
/>
2944

30-
<Paper mb="lg" p="md" radius="md" withBorder>
31-
<Stack gap="md">
32-
<Title order={4}>
33-
{t('subscription-settings.page.component.what-is-subscription-settings')}
34-
</Title>
35-
36-
<Text c="dimmed" size="sm">
37-
{t(
38-
'subscription-settings.page.component.subscription-settings-description'
39-
)}{' '}
40-
<br />
41-
{t(
42-
'subscription-settings.page.component.subscription-settings-description-line-2'
43-
)}
44-
</Text>
45-
</Stack>
46-
</Paper>
47-
48-
<SubscriptionSettingsWidget subscriptionSettings={subscriptionSettings} />
45+
<Container fluid p={0} size="xl">
46+
<Paper mb="xl" p="md" radius="md" shadow="sm" withBorder>
47+
<Group align="flex-start" wrap="nowrap">
48+
<Avatar
49+
color="white"
50+
radius="md"
51+
size="lg"
52+
style={{
53+
backgroundColor: 'var(--mantine-color-gray-7)',
54+
borderRadius: 'var(--mantine-radius-md)',
55+
alignItems: 'center',
56+
background: rgba(primaryColor, 0.15),
57+
backdropFilter: 'blur(8px)',
58+
boxShadow: `0 4px 12px ${rgba(primaryColor, 0.1)}`
59+
}}
60+
>
61+
<PiBarcode size={34} />
62+
</Avatar>
63+
64+
<Stack gap="xs">
65+
<Title fw={600} order={4}>
66+
{t(
67+
'subscription-settings.page.component.what-is-subscription-settings'
68+
)}
69+
</Title>
70+
71+
<Text c="dimmed" lh={1.6} size="sm">
72+
{t(
73+
'subscription-settings.page.component.subscription-settings-description'
74+
)}{' '}
75+
<br />
76+
{t(
77+
'subscription-settings.page.component.subscription-settings-description-line-2'
78+
)}
79+
</Text>
80+
</Stack>
81+
</Group>
82+
</Paper>
83+
84+
<Box mb="xl">
85+
<SubscriptionSettingsWidget subscriptionSettings={subscriptionSettings} />
86+
</Box>
87+
</Container>
4988
</Page>
5089
)
5190
}
Lines changed: 84 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Button, Group, Paper, Stack, Text, Title } from '@mantine/core'
1+
import { Avatar, Button, Container, Group, Paper, Stack, Text, Title } from '@mantine/core'
22
import { PiBookOpenTextDuotone } from 'react-icons/pi'
33
import { useTranslation } from 'react-i18next'
44
import { Link } from 'react-router-dom'
@@ -8,6 +8,42 @@ import { ROUTES } from '@shared/constants'
88
import { PageHeader } from '@shared/ui'
99
import { Page } from '@shared/ui/page'
1010

11+
const HappLogo = () => (
12+
<svg
13+
height="48"
14+
preserveAspectRatio="xMidYMid meet"
15+
style={{ borderRadius: '8px', overflow: 'hidden' }}
16+
viewBox="0 0 460 460"
17+
width="48"
18+
xmlns="http://www.w3.org/2000/svg"
19+
>
20+
<g
21+
fill="currentColor"
22+
stroke="none"
23+
transform="translate(0.000000,460.000000) scale(0.100000,-0.100000)"
24+
>
25+
<path
26+
d="M0 2300 l0 -2300 2300 0 2300 0 0 2300 0 2300 -2300 0 -2300 0 0
27+
-2300z m2095 1528 c-2 -13 -16 -93 -30 -178 l-26 -155 -427 -421 c-235 -232
28+
-428 -421 -428 -420 -1 0 44 270 99 599 l101 597 358 0 358 0 -5 -22z m1420 0
29+
c-3 -13 -17 -92 -31 -177 l-25 -155 -421 -415 c-231 -229 -424 -417 -428 -419
30+
-4 -1 37 260 91 580 54 321 99 589 99 596 0 9 79 12 360 12 l360 0 -5 -22z
31+
m-1441 -788 c-40 -239 -74 -443 -74 -452 0 -17 20 -18 272 -18 l273 0 -265
32+
-265 -264 -264 -55 -3 -55 -3 -11 -60 -11 -60 -424 -422 c-234 -232 -426 -420
33+
-427 -419 -2 1 56 353 127 782 l130 779 426 423 c235 233 428 422 429 420 2
34+
-2 -30 -199 -71 -438z m1492 409 c-3 -17 -62 -369 -132 -782 l-125 -752 -427
35+
-421 c-235 -232 -428 -421 -429 -420 0 0 35 212 78 471 43 258 79 475 79 482
36+
0 10 -55 13 -247 13 l-248 0 265 265 c216 216 269 265 294 267 27 3 31 7 34
37+
35 3 28 63 91 430 453 235 231 429 420 431 420 2 0 1 -14 -3 -31z m-1644
38+
-2122 l-97 -577 -358 0 -359 0 6 28 c3 15 15 83 26 152 12 68 23 127 25 130
39+
14 17 850 848 852 846 1 -1 -41 -262 -95 -579z m1430 0 l-97 -577 -358 0 -359
40+
0 6 28 c3 15 15 85 27 156 l21 129 427 423 c234 232 427 421 428 420 1 -1 -41
41+
-262 -95 -579z"
42+
/>
43+
</g>
44+
</svg>
45+
)
46+
1147
export const HappRoutingBuilderPageComponent = () => {
1248
const { t } = useTranslation()
1349

@@ -19,35 +55,54 @@ export const HappRoutingBuilderPageComponent = () => {
1955
breadcrumbs={[{ label: t('constants.dashboard'), href: ROUTES.DASHBOARD.HOME }]}
2056
title={title}
2157
/>
22-
<Paper mb="lg" p="md" radius="md" withBorder>
23-
<Stack gap="md">
24-
<Title order={4}>{t('happ-routing-builder.page.component.about-happ')}</Title>
25-
26-
<Text c="dimmed" size="sm">
27-
{t('happ-routing-builder.page.component.happ-is-multiplatform-xray-client')}
28-
<br />
29-
{t('happ-routing-builder.page.component.about-happ-description-line-2')}
30-
<br />
31-
<b>
32-
{t('happ-routing-builder.page.component.about-happ-description-line-3')}
33-
</b>
34-
</Text>
35-
36-
<Group>
37-
<Button
38-
component={Link}
39-
leftSection={<PiBookOpenTextDuotone size="1.2rem" />}
40-
rel="noopener noreferrer"
41-
target="_blank"
42-
to={'https://www.happ.su/main/developer-documentation/routing'}
43-
variant="light"
44-
>
45-
{t('happ-routing-builder.page.component.check-out-happ-website')}
46-
</Button>
58+
<Container fluid p={0} size="xl">
59+
<Paper mb="xl" p="md" radius="md" shadow="sm" withBorder>
60+
<Group align="flex-start" wrap="nowrap">
61+
<Avatar radius="md" size="lg" variant="transparent">
62+
<HappLogo />
63+
</Avatar>
64+
65+
<Stack gap="xs">
66+
<Title fw={600} order={4}>
67+
{t('happ-routing-builder.page.component.about-happ')}
68+
</Title>
69+
70+
<Text c="dimmed" lh={1.6} size="sm">
71+
{t(
72+
'happ-routing-builder.page.component.happ-is-multiplatform-xray-client'
73+
)}
74+
<br />
75+
{t(
76+
'happ-routing-builder.page.component.about-happ-description-line-2'
77+
)}
78+
<br />
79+
<b>
80+
{t(
81+
'happ-routing-builder.page.component.about-happ-description-line-3'
82+
)}
83+
</b>
84+
</Text>
85+
86+
<Group>
87+
<Button
88+
component={Link}
89+
leftSection={<PiBookOpenTextDuotone size="1.2rem" />}
90+
rel="noopener noreferrer"
91+
target="_blank"
92+
to={'https://www.happ.su/main/developer-documentation/routing'}
93+
variant="light"
94+
>
95+
{t(
96+
'happ-routing-builder.page.component.check-out-happ-website'
97+
)}
98+
</Button>
99+
</Group>
100+
</Stack>
47101
</Group>
48-
</Stack>
49-
</Paper>
50-
<HappRoutingBuilderWidget />
102+
</Paper>
103+
104+
<HappRoutingBuilderWidget />
105+
</Container>
51106
</Page>
52107
)
53108
}

src/shared/ui/metrics/metric-card/metric-card-root.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ import { Card, CardProps, ElementProps } from '@mantine/core'
33
type MetricCardRootProps = CardProps & ElementProps<'div', keyof CardProps>
44

55
export function MetricCardRoot({ ...props }: MetricCardRootProps) {
6-
return <Card {...props} />
6+
return <Card p="md" radius="md" shadow="sm" withBorder {...props} />
77
}

src/shared/ui/metrics/metric-card/metric-card-text-icon.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
1-
import { Box, BoxProps, ElementProps } from '@mantine/core'
1+
import { Box, BoxProps, ElementProps, rgba, useMantineTheme } from '@mantine/core'
22

33
type MetricCardIcon = ElementProps<'div', keyof BoxProps> & Omit<BoxProps, 'children'>
44

55
export function MetricCardIcon({ display = 'flex', ...props }: MetricCardIcon) {
6+
const theme = useMantineTheme()
7+
const primaryColor = theme.colors[theme.primaryColor][6]
8+
69
return (
710
<Box
811
display={display}
12+
p="xs"
913
{...props}
1014
style={{
1115
borderRadius: 'var(--mantine-radius-md)',
1216
alignItems: 'center',
13-
justifyContent: 'center'
17+
background: rgba(primaryColor, 0.15),
18+
backdropFilter: 'blur(8px)',
19+
boxShadow: `0 4px 12px ${rgba(primaryColor, 0.1)}`
1420
}}
1521
/>
1622
)
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Group } from '@mantine/core'
1+
import { Group, Stack } from '@mantine/core'
22

33
import { MetricCard } from '@shared/ui/metrics/metric-card'
44

@@ -7,13 +7,13 @@ import { MetricWithIconProps } from './interfaces/iprops'
77
export const MetricWithIcon = (props: MetricWithIconProps) => (
88
<MetricCard.Root key={props.title}>
99
<Group>
10-
<MetricCard.Icon c={props.color}>
11-
<props.icon size="2rem" />
10+
<MetricCard.Icon c={props.color} p="sm">
11+
<props.icon size="1.8rem" />
1212
</MetricCard.Icon>
13-
<div>
13+
<Stack align="self-start" gap="xs">
1414
<MetricCard.TextMuted>{props.title}</MetricCard.TextMuted>
1515
<MetricCard.TextEmphasis ff={'monospace'}>{props.value}</MetricCard.TextEmphasis>
16-
</div>
16+
</Stack>
1717
</Group>
1818
</MetricCard.Root>
1919
)

src/widgets/dashboard/subscription-settings/settings/remarks-manager.widget.tsx

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { ActionIcon, Box, Button, Group, Text, TextInput } from '@mantine/core'
2-
import { PiPlus, PiTrash } from 'react-icons/pi'
1+
import { ActionIcon, Button, Group, Paper, Text, TextInput, ThemeIcon } from '@mantine/core'
2+
import { PiNotePencil, PiPlus, PiTrash } from 'react-icons/pi'
33
import { useTranslation } from 'react-i18next'
44
import { useEffect, useState } from 'react'
55

@@ -47,17 +47,25 @@ export const RemarksManager = ({
4747
}
4848

4949
return (
50-
<Box>
51-
<Text fw={500} mb="xs">
52-
{title}
53-
</Text>
50+
<Paper p="sm" radius="md" shadow="xs" withBorder>
51+
<Group align="center" gap="xs" justify="flex-start" mb="md">
52+
<ThemeIcon color="blue" radius="md" size="md" variant="light">
53+
<PiNotePencil size="1rem" />
54+
</ThemeIcon>
55+
<Text fw={600} size="sm">
56+
{title}
57+
</Text>
58+
</Group>
59+
5460
{localRemarks.map((remark, index) => (
5561
<Group align="flex-start" gap="sm" key={index} mb="xs">
5662
<ActionIcon
5763
color="red"
5864
disabled={localRemarks.length === 1}
5965
onClick={() => removeLocalRemark(index)}
66+
radius="md"
6067
size="lg"
68+
variant="light"
6169
>
6270
<PiTrash size="1rem" />
6371
</ActionIcon>
@@ -78,6 +86,6 @@ export const RemarksManager = ({
7886
>
7987
{t('remarks-manager.widget.add-remark')}
8088
</Button>
81-
</Box>
89+
</Paper>
8290
)
8391
}

0 commit comments

Comments
 (0)