Skip to content

Commit d286826

Browse files
committed
refactor: subpage constants and models
1 parent 600ed9b commit d286826

File tree

17 files changed

+486
-205
lines changed

17 files changed

+486
-205
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { TSubscriptionPageBaseTranslationKeys } from '../models';
2+
3+
export const BASE_TRANSLATION_LABELS: Record<TSubscriptionPageBaseTranslationKeys, string> = {
4+
installationGuideHeader: 'Installation Guide Header',
5+
connectionKeysHeader: 'Connection Keys Header',
6+
linkCopied: 'Link Copied',
7+
linkCopiedToClipboard: 'Link Copied to Clipboard',
8+
getLink: 'Get Link',
9+
scanQrCode: 'Scan QR Code',
10+
scanQrCodeDescription: 'Scan QR Code Description',
11+
copyLink: 'Copy Link',
12+
name: 'Name',
13+
status: 'Status',
14+
active: 'Active',
15+
inactive: 'Inactive',
16+
expires: 'Expires',
17+
bandwidth: 'Bandwidth',
18+
scanToImport: 'Scan to Import',
19+
expiresIn: 'Expires In',
20+
expired: 'Expired',
21+
unknown: 'Unknown',
22+
indefinitely: 'Indefinitely',
23+
};
24+
25+
export const BASE_TRANSLATION_KEYS: TSubscriptionPageBaseTranslationKeys[] = Object.keys(
26+
BASE_TRANSLATION_LABELS,
27+
) as TSubscriptionPageBaseTranslationKeys[];
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
export * from './app-config.constant';
2+
export * from './base-translations.constant';
23
export * from './button-types.constant';
3-
export * from './installation-guide-blocks.constant';
4-
export * from './subscription-info-blocks.constant';
5-
export * from './subscription-page-config';
4+
export * from './language-codes.constant';
5+
export * from './platform-types.constant';
6+
export * from './template-keys.constant';
7+
export * from './ui-blocks-variants.constant';
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
const LANGUAGES_LIST = {
2+
en: { name: 'English', nativeName: 'English', emoji: '🇬🇧' },
3+
ru: { name: 'Russian', nativeName: 'Русский', emoji: '🇷🇺' },
4+
zh: { name: 'Chinese', nativeName: '中文', emoji: '🇨🇳' },
5+
fr: { name: 'French', nativeName: 'Français', emoji: '🇫🇷' },
6+
fa: { name: 'Persian', nativeName: 'فارسی', emoji: '🇮🇷' },
7+
uz: { name: 'Uzbek', nativeName: 'Ўзбек', emoji: '🇺🇿' },
8+
de: { name: 'German', nativeName: 'Deutsch', emoji: '🇩🇪' },
9+
hi: { name: 'Hindi', nativeName: 'हिन्दी', emoji: '🇮🇳' },
10+
tr: { name: 'Turkish', nativeName: 'Türkçe', emoji: '🇹🇷' },
11+
az: { name: 'Azerbaijani', nativeName: 'azərbaycan dili', emoji: '🇦🇿' },
12+
es: { name: 'Spanish', nativeName: 'Español', emoji: '🇪🇸' },
13+
vi: { name: 'Vietnamese', nativeName: 'Tiếng Việt', emoji: '🇻🇳' },
14+
ja: { name: 'Japanese', nativeName: '日本語', emoji: '🇯🇵' },
15+
be: { name: 'Belarusian', nativeName: 'беларуская мова', emoji: '🇧🇾' },
16+
uk: { name: 'Ukrainian', nativeName: 'Українська', emoji: '🇺🇦' },
17+
pt: { name: 'Portuguese', nativeName: 'Português', emoji: '🇵🇹' },
18+
pl: { name: 'Polish', nativeName: 'Polski', emoji: '🇵🇱' },
19+
id: { name: 'Indonesian', nativeName: 'Bahasa Indonesia', emoji: '🇮🇩' },
20+
tk: { name: 'Turkmen', nativeName: 'Türkmençe', emoji: '🇹🇲' },
21+
th: { name: 'Thai', nativeName: 'ไทย', emoji: '🇹🇭' },
22+
} as const;
23+
24+
export type TSubscriptionPageLanguageCode = keyof typeof LANGUAGES_LIST;
25+
26+
export const LANGUAGE_CODES = Object.keys(LANGUAGES_LIST) as [
27+
TSubscriptionPageLanguageCode,
28+
...TSubscriptionPageLanguageCode[],
29+
];
30+
31+
export interface ILanguageInfo {
32+
name: string;
33+
nativeName: string;
34+
emoji: string;
35+
}
36+
37+
/**
38+
* Get language info by code
39+
* @param code - ISO 639-1 language code
40+
* @returns Language info object with name and nativeName
41+
*/
42+
export const getLanguageInfo = (code: string): ILanguageInfo | null => {
43+
if (isLanguageCode(code)) {
44+
return LANGUAGES_LIST[code];
45+
}
46+
return null;
47+
};
48+
49+
/**
50+
* Get language name (English) by code
51+
* @param code - ISO 639-1 language code
52+
* @returns English language name or the code itself if not found
53+
*/
54+
55+
export const getLanguageName = (code: string): string => {
56+
if (isLanguageCode(code)) {
57+
return LANGUAGES_LIST[code].name;
58+
}
59+
return code;
60+
};
61+
62+
/**
63+
* Get native language name by code
64+
* @param code - ISO 639-1 language code
65+
* @returns Native language name or the code itself if not found
66+
*/
67+
export const getLanguageNativeName = (code: string): string => {
68+
if (isLanguageCode(code)) {
69+
return LANGUAGES_LIST[code].nativeName;
70+
}
71+
return code;
72+
};
73+
74+
/**
75+
* Check if a string is a valid language code
76+
*/
77+
export const isLanguageCode = (code: string): code is TSubscriptionPageLanguageCode => {
78+
return code in LANGUAGES_LIST;
79+
};
80+
81+
/**
82+
* Get all languages as array for UI selects
83+
*/
84+
export const getLanguagesArray = (): Array<
85+
{ code: TSubscriptionPageLanguageCode } & ILanguageInfo
86+
> => {
87+
return (Object.entries(LANGUAGES_LIST) as [TSubscriptionPageLanguageCode, ILanguageInfo][]).map(
88+
([code, info]) => ({
89+
code,
90+
...info,
91+
}),
92+
);
93+
};

libs/subscription-page/constants/subscription-page-config/subscription-page-config.contants.ts renamed to libs/subscription-page/constants/platform-types.constant.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ export const SUBSCRIPTION_PAGE_CONFIG_VERSION = {
22
1: '1',
33
} as const;
44

5-
export const SUBSCRIPTION_PAGE_CONFIG_ADDITIONAL_LOCALES = ['ru', 'zh', 'fa', 'fr'] as const;
5+
export type TSubscriptionPageConfigVersion =
6+
(typeof SUBSCRIPTION_PAGE_CONFIG_VERSION)[keyof typeof SUBSCRIPTION_PAGE_CONFIG_VERSION];
67

78
export const SUBSCRIPTION_PAGE_CONFIG_PLATFORM_TYPES = {
89
IOS: 'ios',
@@ -14,5 +15,5 @@ export const SUBSCRIPTION_PAGE_CONFIG_PLATFORM_TYPES = {
1415
APPLE_TV: 'appleTV',
1516
} as const;
1617

17-
export type TSubscriptionPageConfigAdditionalLocales =
18-
(typeof SUBSCRIPTION_PAGE_CONFIG_ADDITIONAL_LOCALES)[number];
18+
export type TSubscriptionPageConfigPlatformType =
19+
(typeof SUBSCRIPTION_PAGE_CONFIG_PLATFORM_TYPES)[keyof typeof SUBSCRIPTION_PAGE_CONFIG_PLATFORM_TYPES];

libs/subscription-page/constants/subscription-info-blocks.constant.ts

Lines changed: 0 additions & 19 deletions
This file was deleted.

libs/subscription-page/constants/subscription-page-config/index.ts

Lines changed: 0 additions & 2 deletions
This file was deleted.

libs/subscription-page/constants/subscription-page-config/subscription-page-template-keys.contant.ts renamed to libs/subscription-page/constants/template-keys.constant.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export const SUBSCRIPTION_PAGE_TEMPLATE_KEYS = ['USERNAME', 'SUBSCRIPTION_LINK'] as const;
2-
export type SubscriptionPageTemplateKeys = (typeof SUBSCRIPTION_PAGE_TEMPLATE_KEYS)[number];
2+
export type TSubscriptionPageTemplateKey = (typeof SUBSCRIPTION_PAGE_TEMPLATE_KEYS)[number];
3+

libs/subscription-page/constants/installation-guide-blocks.constant.ts renamed to libs/subscription-page/constants/ui-blocks-variants.constant.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,24 @@
1+
export const SUBSCRIPTION_INFO_BLOCK_VARIANTS = {
2+
COLLAPSED: 'collapsed',
3+
EXPANDED: 'expanded',
4+
CARDS: 'cards',
5+
HIDDEN: 'hidden',
6+
} as const;
7+
18
export const INSTALLATION_GUIDE_BLOCKS_VARIANTS = {
29
CARDS: 'cards',
310
ACCORDION: 'accordion',
411
MINIMAL: 'minimal',
512
TIMELINE: 'timeline',
613
} as const;
714

15+
export type TSubscriptionInfoBlockVariant =
16+
(typeof SUBSCRIPTION_INFO_BLOCK_VARIANTS)[keyof typeof SUBSCRIPTION_INFO_BLOCK_VARIANTS];
17+
18+
export const SUBSCRIPTION_INFO_BLOCK_VARIANTS_VALUES = Object.values(
19+
SUBSCRIPTION_INFO_BLOCK_VARIANTS,
20+
);
21+
822
export type TInstallationGuideBlockVariant =
923
(typeof INSTALLATION_GUIDE_BLOCKS_VARIANTS)[keyof typeof INSTALLATION_GUIDE_BLOCKS_VARIANTS];
1024

@@ -19,3 +33,9 @@ export const isInstallationGuideBlockVariant = (
1933
value as TInstallationGuideBlockVariant,
2034
);
2135
};
36+
37+
export const isSubscriptionInfoBlockVariant = (
38+
value: string,
39+
): value is TSubscriptionInfoBlockVariant => {
40+
return SUBSCRIPTION_INFO_BLOCK_VARIANTS_VALUES.includes(value as TSubscriptionInfoBlockVariant);
41+
};
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
export * from './subscription-page-config';
1+
export * from './subscription-page-config.schema';
2+
export * from './subscription-page-config.validator';

libs/subscription-page/models/subscription-page-config/subscription-page-config.schema.ts renamed to libs/subscription-page/models/subscription-page-config.schema.ts

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,21 @@ import { z } from 'zod';
33
import {
44
SUBSCRIPTION_PAGE_CONFIG_VERSION,
55
SUBSCRIPTION_PAGE_CONFIG_PLATFORM_TYPES,
6-
SUBSCRIPTION_PAGE_CONFIG_ADDITIONAL_LOCALES,
76
SUBSCRIPTION_INFO_BLOCK_VARIANTS,
87
INSTALLATION_GUIDE_BLOCKS_VARIANTS,
98
BUTTON_TYPES,
10-
} from '../../constants';
9+
LANGUAGE_CODES,
10+
} from '../constants';
1111
import {
1212
validateLocalizedTexts,
1313
validateSvgReferences,
1414
} from './subscription-page-config.validator';
1515

16-
export const LocalizedTextSchema = z.object({
17-
en: z.string(),
18-
ru: z.string().optional(),
19-
zh: z.string().optional(),
20-
fa: z.string().optional(),
21-
fr: z.string().optional(),
22-
});
16+
const LocalizedTextSchema = z
17+
.record(z.string().regex(/^[a-z]{2}$/, 'Language code must be 2 lowercase letters'), z.string())
18+
.refine((obj) => Object.keys(obj).length > 0, {
19+
message: 'At least one language must be specified',
20+
});
2321

2422
const SvgLibrarySchema = z.record(
2523
z.string().regex(/^[A-Za-z]+$/, { message: 'Only latin characters, no spaces allowed' }),
@@ -67,6 +65,7 @@ const BlockSchema = z.object({
6765

6866
const PlatformAppSchema = z.object({
6967
name: z.string(),
68+
svgIconKey: z.optional(z.string()),
7069
featured: z.boolean(),
7170
blocks: z.array(BlockSchema),
7271
});
@@ -84,31 +83,44 @@ const BrandingSettingsSchema = z.object({
8483
});
8584

8685
const UiConfigSchema = z.object({
87-
subscriptionInfo: z.object({
88-
block: z.nativeEnum(SUBSCRIPTION_INFO_BLOCK_VARIANTS),
89-
}),
90-
installationGuides: z.object({
91-
block: z
92-
.nativeEnum(INSTALLATION_GUIDE_BLOCKS_VARIANTS)
93-
.default(INSTALLATION_GUIDE_BLOCKS_VARIANTS.CARDS),
94-
headerText: LocalizedTextSchema,
95-
}),
96-
connectionKeys: z.object({
97-
headerText: LocalizedTextSchema,
98-
}),
86+
subscriptionInfoBlockType: z.nativeEnum(SUBSCRIPTION_INFO_BLOCK_VARIANTS),
87+
installationGuidesBlockType: z.nativeEnum(INSTALLATION_GUIDE_BLOCKS_VARIANTS),
88+
});
89+
90+
const SubscriptionPageTranslateKeysSchema = z.object({
91+
installationGuideHeader: LocalizedTextSchema,
92+
connectionKeysHeader: LocalizedTextSchema,
93+
linkCopied: LocalizedTextSchema,
94+
linkCopiedToClipboard: LocalizedTextSchema,
95+
getLink: LocalizedTextSchema,
96+
scanQrCode: LocalizedTextSchema,
97+
scanQrCodeDescription: LocalizedTextSchema,
98+
copyLink: LocalizedTextSchema,
99+
name: LocalizedTextSchema,
100+
status: LocalizedTextSchema,
101+
active: LocalizedTextSchema,
102+
inactive: LocalizedTextSchema,
103+
expires: LocalizedTextSchema,
104+
bandwidth: LocalizedTextSchema,
105+
scanToImport: LocalizedTextSchema,
106+
expiresIn: LocalizedTextSchema,
107+
expired: LocalizedTextSchema,
108+
unknown: LocalizedTextSchema,
109+
indefinitely: LocalizedTextSchema,
99110
});
100111

101112
export const SubscriptionPageRawConfigSchema = z
102113
.object({
103114
version: z.nativeEnum(SUBSCRIPTION_PAGE_CONFIG_VERSION),
104-
additionalLocales: z.array(z.enum(SUBSCRIPTION_PAGE_CONFIG_ADDITIONAL_LOCALES)),
115+
locales: z.array(z.enum(LANGUAGE_CODES)).min(1, 'At least one locale must be specified'),
105116
brandingSettings: BrandingSettingsSchema,
106117
uiConfig: UiConfigSchema,
118+
baseTranslations: SubscriptionPageTranslateKeysSchema,
107119
svgLibrary: SvgLibrarySchema,
108120
platforms: z.record(z.nativeEnum(SUBSCRIPTION_PAGE_CONFIG_PLATFORM_TYPES), PlatformSchema),
109121
})
110122
.superRefine((data, ctx) => {
111-
validateLocalizedTexts(data.platforms, data.additionalLocales, 'platforms', ctx);
123+
validateLocalizedTexts(data, data.locales, ctx);
112124
validateSvgReferences(data, ctx);
113125
});
114126

@@ -122,6 +134,5 @@ export type TSubscriptionPageBlockConfig = z.infer<typeof BlockSchema>;
122134
export type TSubscriptionPageButtonConfig = z.infer<typeof ButtonSchema>;
123135
export type TSubscriptionPageLocalizedText = z.infer<typeof LocalizedTextSchema>;
124136
export type TSubscriptionPageUiConfig = z.infer<typeof UiConfigSchema>;
125-
export type TSubscriptionPageLocales =
126-
| TSubscriptionPageRawConfig['additionalLocales'][number]
127-
| 'en';
137+
export type TSubscriptionPageTranslateKeys = z.infer<typeof SubscriptionPageTranslateKeysSchema>;
138+
export type TSubscriptionPageBaseTranslationKeys = keyof TSubscriptionPageTranslateKeys;

0 commit comments

Comments
 (0)