@nathapp/na-cli 1.0.8 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/templates/db-schema/.gitlab-ci.yml +139 -0
- package/dist/templates/db-schema/Makefile +885 -0
- package/dist/templates/k8s-deployment/.gitlab-ci.yml +158 -0
- package/dist/templates/k8s-deployment/Makefile +233 -0
- package/dist/templates/k8s-deployment/resources/charts/mysql/charts/mysql-install/script/Makefile +12 -0
- package/dist/templates/k8s-deployment/resources/charts/redis/charts/redis-install/script/Makefile +8 -0
- package/dist/templates/k8s-deployment/services/charts/hooks/charts/pre-delete-rsc/script/Makefile +56 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-cypress/Makefile +9 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/script/Makefile +14 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/_t-0100-readiness-liveness.ts +84 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/hub.ts +372 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-contact.ts +158 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-contract.ts +328 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-kyc.ts +304 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-onboard-app.ts +823 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-onboard-web.ts +493 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-profile.ts +277 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/individual-whitelist.ts +133 -0
- package/dist/templates/k8s-deployment/services/charts/tests/charts/e2e-test-js/tests/t-0200-start.ts +172 -0
- package/dist/templates/nestjs-api/.dockerignore +9 -0
- package/dist/templates/nestjs-api/.env +35 -0
- package/dist/templates/nestjs-api/.env.local +5 -29
- package/dist/templates/nestjs-api/.gitlab-ci.yml +180 -0
- package/dist/templates/nestjs-api/.nvmrc +1 -0
- package/dist/templates/nestjs-api/.prettierrc +4 -0
- package/dist/templates/nestjs-api/Makefile +95 -0
- package/dist/templates/nestjs-api/README.md +15 -0
- package/dist/templates/nestjs-api/nest-cli.json +10 -0
- package/dist/templates/nestjs-api/ormconfig.ts +16 -0
- package/dist/templates/nestjs-api/package.json +9 -9
- package/dist/templates/nestjs-api/src/app.controller.spec.ts +24 -0
- package/dist/templates/nestjs-api/src/app.controller.ts +27 -0
- package/dist/templates/nestjs-api/src/app.module.ts +33 -0
- package/dist/templates/nestjs-api/src/app.service.ts +27 -0
- package/dist/templates/nestjs-api/src/main.ts +31 -0
- package/dist/templates/nestjs-api/test/app.e2e-spec.ts +47 -0
- package/dist/templates/nestjs-api/tsconfig.build.json +5 -0
- package/dist/templates/nestjs-api/tsconfig.json +28 -0
- package/dist/templates/nestjs-api/tsconfig.spec.json +9 -0
- package/dist/templates/nestjs-library/.gitlab-ci.yml +134 -0
- package/dist/templates/nestjs-library/.nvmrc +1 -0
- package/dist/templates/nestjs-library/.prettierrc +6 -0
- package/dist/templates/nestjs-library/Makefile +60 -0
- package/dist/templates/nestjs-library/lib/index.ts +2 -0
- package/dist/templates/nestjs-library/test/app/controller/hello.controller.spec.ts +20 -0
- package/dist/templates/nestjs-library/test/app/controller/hello.controller.ts +7 -0
- package/dist/templates/nestjs-library/tsconfig.build.json +8 -0
- package/dist/templates/nestjs-library/tsconfig.json +21 -0
- package/dist/templates/nestjs-library/tsconfig.spec.json +9 -0
- package/dist/templates/ts-library/.dockerignore +2 -0
- package/dist/templates/ts-library/.eslintrc.js +24 -0
- package/dist/templates/ts-library/.gitlab-ci.yml +136 -0
- package/dist/templates/ts-library/.prettierrc +6 -0
- package/dist/templates/ts-library/Makefile +58 -0
- package/dist/templates/ts-library/index.ts +1 -0
- package/dist/templates/ts-library/lib/index.ts +1 -0
- package/dist/templates/ts-library/lib/samples/index.ts +5 -0
- package/dist/templates/ts-library/lib/samples/samples-function.ts +3 -0
- package/dist/templates/ts-library/test/sample.e2e-spec.ts +10 -0
- package/dist/templates/ts-library/tsconfig.build.json +4 -0
- package/dist/templates/ts-library/tsconfig.json +18 -0
- package/dist/templates/turbo-nestjs-vuexy/.dockerignore +2 -0
- package/dist/templates/turbo-nestjs-vuexy/.gitignore-rename +40 -0
- package/dist/templates/turbo-nestjs-vuexy/.npmrc-rename +0 -0
- package/dist/templates/turbo-nestjs-vuexy/Makefile +48 -0
- package/dist/templates/vuexy-portal/.dockerignore +2 -0
- package/dist/templates/vuexy-portal/.env +1 -0
- package/dist/templates/vuexy-portal/.gitlab-ci.yml +233 -0
- package/dist/templates/vuexy-portal/.npmrc-rename +2 -0
- package/dist/templates/vuexy-portal/.nvmrc +1 -0
- package/dist/templates/vuexy-portal/Makefile +55 -0
- package/dist/templates/vuexy-portal/src/@core/composable/createUrl.ts +20 -0
- package/dist/templates/vuexy-portal/src/@core/composable/useCookie.ts +43 -0
- package/dist/templates/vuexy-portal/src/@core/composable/useGenerateImageVariant.ts +25 -0
- package/dist/templates/vuexy-portal/src/@core/composable/useResponsiveSidebar.ts +29 -0
- package/dist/templates/vuexy-portal/src/@core/composable/useSkins.ts +42 -0
- package/dist/templates/vuexy-portal/src/@core/enums.ts +21 -0
- package/dist/templates/vuexy-portal/src/@core/index.ts +43 -0
- package/dist/templates/vuexy-portal/src/@core/initCore.ts +93 -0
- package/dist/templates/vuexy-portal/src/@core/libs/apex-chart/apexCharConfig.ts +701 -0
- package/dist/templates/vuexy-portal/src/@core/libs/chartjs/chartjsConfig.ts +372 -0
- package/dist/templates/vuexy-portal/src/@core/libs/chartjs/components/BarChart.ts +58 -0
- package/dist/templates/vuexy-portal/src/@core/libs/chartjs/components/BubbleChart.ts +58 -0
- package/dist/templates/vuexy-portal/src/@core/libs/chartjs/components/DoughnutChart.ts +58 -0
- package/dist/templates/vuexy-portal/src/@core/libs/chartjs/components/LineChart.ts +58 -0
- package/dist/templates/vuexy-portal/src/@core/libs/chartjs/components/PolarAreaChart.ts +58 -0
- package/dist/templates/vuexy-portal/src/@core/libs/chartjs/components/RadarChart.ts +58 -0
- package/dist/templates/vuexy-portal/src/@core/libs/chartjs/components/ScatterChart.ts +58 -0
- package/dist/templates/vuexy-portal/src/@core/stores/config.ts +80 -0
- package/dist/templates/vuexy-portal/src/@core/types.ts +49 -0
- package/dist/templates/vuexy-portal/src/@core/utils/formatters.ts +48 -0
- package/dist/templates/vuexy-portal/src/@core/utils/helpers.ts +32 -0
- package/dist/templates/vuexy-portal/src/@core/utils/plugins.ts +53 -0
- package/dist/templates/vuexy-portal/src/@core/utils/validators.ts +105 -0
- package/dist/templates/vuexy-portal/src/@core/utils/vuetify.ts +13 -0
- package/dist/templates/vuexy-portal/src/@custom/composables/toasts.ts +45 -0
- package/dist/templates/vuexy-portal/src/@custom/composables/validator.ts +160 -0
- package/dist/templates/vuexy-portal/src/@custom/enums/index.ts +0 -0
- package/dist/templates/vuexy-portal/src/@custom/types/common.ts +17 -0
- package/dist/templates/vuexy-portal/src/@custom/types/index.ts +0 -0
- package/dist/templates/vuexy-portal/src/@custom/types/pagination.ts +19 -0
- package/dist/templates/vuexy-portal/src/@custom/types/user.ts +5 -0
- package/dist/templates/vuexy-portal/src/@custom/utils/formatters.ts +83 -0
- package/dist/templates/vuexy-portal/src/@custom/utils/index.ts +0 -0
- package/dist/templates/vuexy-portal/src/@custom/utils/validators.ts +51 -0
- package/dist/templates/vuexy-portal/src/@layouts/components.ts +11 -0
- package/dist/templates/vuexy-portal/src/@layouts/config.ts +43 -0
- package/dist/templates/vuexy-portal/src/@layouts/enums.ts +27 -0
- package/dist/templates/vuexy-portal/src/@layouts/index.ts +49 -0
- package/dist/templates/vuexy-portal/src/@layouts/plugins/casl.ts +48 -0
- package/dist/templates/vuexy-portal/src/@layouts/stores/config.ts +115 -0
- package/dist/templates/vuexy-portal/src/@layouts/symbols.ts +1 -0
- package/dist/templates/vuexy-portal/src/@layouts/types.ts +126 -0
- package/dist/templates/vuexy-portal/src/@layouts/utils.ts +180 -0
- package/dist/templates/vuexy-portal/src/api/api.ts +1 -0
- package/dist/templates/vuexy-portal/src/api/commonApi.ts +25 -0
- package/dist/templates/vuexy-portal/src/api/index.ts +58 -0
- package/dist/templates/vuexy-portal/src/api/requestInterceptor.ts +21 -0
- package/dist/templates/vuexy-portal/src/api/responseInterceptor.ts +52 -0
- package/dist/templates/vuexy-portal/src/api/types.ts +14 -0
- package/dist/templates/vuexy-portal/src/api/useApi.ts +68 -0
- package/dist/templates/vuexy-portal/src/api/useFetchApi.ts +41 -0
- package/dist/templates/vuexy-portal/src/api/userApi.ts +11 -0
- package/dist/templates/vuexy-portal/src/composables/useApiFetch.ts +48 -0
- package/dist/templates/vuexy-portal/src/composables/useJwt.ts +108 -0
- package/dist/templates/vuexy-portal/src/main.ts +17 -0
- package/dist/templates/vuexy-portal/src/navigation/horizontal/index.ts +5 -0
- package/dist/templates/vuexy-portal/src/navigation/index.ts +7 -0
- package/dist/templates/vuexy-portal/src/navigation/vertical/index.ts +5 -0
- package/dist/templates/vuexy-portal/src/plugins/1.router/additional-routes.ts +23 -0
- package/dist/templates/vuexy-portal/src/plugins/1.router/guards.ts +50 -0
- package/dist/templates/vuexy-portal/src/plugins/1.router/index.ts +45 -0
- package/dist/templates/vuexy-portal/src/plugins/2.pinia.ts +8 -0
- package/dist/templates/vuexy-portal/src/plugins/casl/ability.ts +10 -0
- package/dist/templates/vuexy-portal/src/plugins/casl/composables/useAbility.ts +4 -0
- package/dist/templates/vuexy-portal/src/plugins/casl/index.ts +14 -0
- package/dist/templates/vuexy-portal/src/plugins/i18n/index.ts +29 -0
- package/dist/templates/vuexy-portal/src/plugins/iconify/build-icons.ts +299 -0
- package/dist/templates/vuexy-portal/src/plugins/iconify/index.ts +5 -0
- package/dist/templates/vuexy-portal/src/plugins/layouts.ts +13 -0
- package/dist/templates/vuexy-portal/src/plugins/toast/index.ts +9 -0
- package/dist/templates/vuexy-portal/src/plugins/vuetify/defaults.ts +192 -0
- package/dist/templates/vuexy-portal/src/plugins/vuetify/icons.ts +84 -0
- package/dist/templates/vuexy-portal/src/plugins/vuetify/index.ts +47 -0
- package/dist/templates/vuexy-portal/src/plugins/vuetify/theme.ts +155 -0
- package/dist/templates/vuexy-portal/src/plugins/webfontloader.ts +19 -0
- package/dist/templates/vuexy-portal/src/stores/auth.ts +22 -0
- package/dist/templates/vuexy-portal/src/stores/common.ts +41 -0
- package/dist/templates/vuexy-portal/src/stores/index.ts +0 -0
- package/dist/templates/vuexy-portal/src/utils/constants.ts +3 -0
- package/dist/templates/vuexy-portal/src/utils/paginationMeta.ts +10 -0
- package/dist/templates/vuexy-portal/themeConfig.ts +66 -0
- package/dist/templates/vuexy-portal/tsconfig.json +86 -0
- package/dist/templates/vuexy-portal/vite.config.ts +111 -0
- package/dist/utils/jwt-keys.js +26 -0
- package/dist/utils/jwt-keys.js.map +1 -0
- package/dist/utils/template.js +4 -1
- package/dist/utils/template.js.map +1 -1
- package/package.json +4 -1
- package/alias-script.sh +0 -30
- package/bunfig.toml +0 -3
- package/nax/config.json +0 -23
- package/nax/features/enhancements/prd.json +0 -61
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { PluginOptionsByType } from 'chart.js'
|
|
2
|
+
import { CategoryScale, Chart as ChartJS, Legend, LineElement, LinearScale, PointElement, Title, Tooltip } from 'chart.js'
|
|
3
|
+
import type { PropType } from 'vue'
|
|
4
|
+
import { defineComponent } from 'vue'
|
|
5
|
+
import { Scatter } from 'vue-chartjs'
|
|
6
|
+
|
|
7
|
+
ChartJS.register(Title, Tooltip, Legend, PointElement, LineElement, CategoryScale, LinearScale)
|
|
8
|
+
|
|
9
|
+
export default defineComponent({
|
|
10
|
+
name: 'ScatterChart',
|
|
11
|
+
props: {
|
|
12
|
+
chartId: {
|
|
13
|
+
type: String,
|
|
14
|
+
default: 'scatter-chart',
|
|
15
|
+
},
|
|
16
|
+
width: {
|
|
17
|
+
type: Number,
|
|
18
|
+
default: 400,
|
|
19
|
+
},
|
|
20
|
+
height: {
|
|
21
|
+
type: Number,
|
|
22
|
+
default: 400,
|
|
23
|
+
},
|
|
24
|
+
cssClasses: {
|
|
25
|
+
default: '',
|
|
26
|
+
type: String,
|
|
27
|
+
},
|
|
28
|
+
styles: {
|
|
29
|
+
type: Object as PropType<Partial<CSSStyleDeclaration>>,
|
|
30
|
+
default: () => ({}),
|
|
31
|
+
},
|
|
32
|
+
plugins: {
|
|
33
|
+
type: Array as PropType<PluginOptionsByType<'scatter'>[]>,
|
|
34
|
+
default: () => [],
|
|
35
|
+
},
|
|
36
|
+
chartData: {
|
|
37
|
+
type: Object,
|
|
38
|
+
default: () => ({}),
|
|
39
|
+
},
|
|
40
|
+
chartOptions: {
|
|
41
|
+
type: Object,
|
|
42
|
+
default: () => ({}),
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
setup(props) {
|
|
46
|
+
return () =>
|
|
47
|
+
h(h(Scatter), {
|
|
48
|
+
data: props.chartData,
|
|
49
|
+
options: props.chartOptions,
|
|
50
|
+
chartId: props.chartId,
|
|
51
|
+
width: props.width,
|
|
52
|
+
height: props.height,
|
|
53
|
+
cssClasses: props.cssClasses,
|
|
54
|
+
styles: props.styles,
|
|
55
|
+
plugins: props.plugins,
|
|
56
|
+
})
|
|
57
|
+
},
|
|
58
|
+
})
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { storeToRefs } from 'pinia'
|
|
2
|
+
import { useTheme } from 'vuetify'
|
|
3
|
+
import { cookieRef, useLayoutConfigStore } from '@layouts/stores/config'
|
|
4
|
+
import { themeConfig } from '@themeConfig'
|
|
5
|
+
|
|
6
|
+
// SECTION Store
|
|
7
|
+
export const useConfigStore = defineStore('config', () => {
|
|
8
|
+
// 👉 Theme
|
|
9
|
+
const userPreferredColorScheme = usePreferredColorScheme()
|
|
10
|
+
const cookieColorScheme = cookieRef<'light' | 'dark'>('color-scheme', 'light')
|
|
11
|
+
|
|
12
|
+
watch(
|
|
13
|
+
userPreferredColorScheme,
|
|
14
|
+
val => {
|
|
15
|
+
if (val !== 'no-preference')
|
|
16
|
+
cookieColorScheme.value = val
|
|
17
|
+
},
|
|
18
|
+
{ immediate: true },
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
const theme = cookieRef('theme', themeConfig.app.theme)
|
|
22
|
+
|
|
23
|
+
// 👉 isVerticalNavSemiDark
|
|
24
|
+
const isVerticalNavSemiDark = cookieRef('isVerticalNavSemiDark', themeConfig.verticalNav.isVerticalNavSemiDark)
|
|
25
|
+
|
|
26
|
+
// 👉 isVerticalNavSemiDark
|
|
27
|
+
const skin = cookieRef('skin', themeConfig.app.skin)
|
|
28
|
+
|
|
29
|
+
// ℹ️ We need to use `storeToRefs` to forward the state
|
|
30
|
+
const {
|
|
31
|
+
isLessThanOverlayNavBreakpoint,
|
|
32
|
+
appContentWidth,
|
|
33
|
+
navbarType,
|
|
34
|
+
isNavbarBlurEnabled,
|
|
35
|
+
appContentLayoutNav,
|
|
36
|
+
isVerticalNavCollapsed,
|
|
37
|
+
footerType,
|
|
38
|
+
isAppRTL,
|
|
39
|
+
} = storeToRefs(useLayoutConfigStore())
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
theme,
|
|
43
|
+
isVerticalNavSemiDark,
|
|
44
|
+
skin,
|
|
45
|
+
|
|
46
|
+
// @layouts exports
|
|
47
|
+
isLessThanOverlayNavBreakpoint,
|
|
48
|
+
appContentWidth,
|
|
49
|
+
navbarType,
|
|
50
|
+
isNavbarBlurEnabled,
|
|
51
|
+
appContentLayoutNav,
|
|
52
|
+
isVerticalNavCollapsed,
|
|
53
|
+
footerType,
|
|
54
|
+
isAppRTL,
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
// !SECTION
|
|
58
|
+
|
|
59
|
+
// SECTION Init
|
|
60
|
+
export const initConfigStore = () => {
|
|
61
|
+
const userPreferredColorScheme = usePreferredColorScheme()
|
|
62
|
+
const vuetifyTheme = useTheme()
|
|
63
|
+
const configStore = useConfigStore()
|
|
64
|
+
|
|
65
|
+
watch(
|
|
66
|
+
[() => configStore.theme, userPreferredColorScheme],
|
|
67
|
+
() => {
|
|
68
|
+
vuetifyTheme.global.name.value = configStore.theme === 'system'
|
|
69
|
+
? userPreferredColorScheme.value === 'dark'
|
|
70
|
+
? 'dark'
|
|
71
|
+
: 'light'
|
|
72
|
+
: configStore.theme
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
onMounted(() => {
|
|
76
|
+
if (configStore.theme === 'system')
|
|
77
|
+
vuetifyTheme.global.name.value = userPreferredColorScheme.value
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
// !SECTION
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { LiteralUnion, ValueOf } from 'type-fest'
|
|
2
|
+
import type { Skins } from './enums'
|
|
3
|
+
import type { I18nLanguage, LayoutConfig } from '@layouts/types'
|
|
4
|
+
|
|
5
|
+
interface ExplicitThemeConfig {
|
|
6
|
+
app: {
|
|
7
|
+
i18n: {
|
|
8
|
+
defaultLocale: string
|
|
9
|
+
langConfig: I18nLanguage[]
|
|
10
|
+
}
|
|
11
|
+
theme: LiteralUnion<'light' | 'dark' | 'system', string>
|
|
12
|
+
skin: ValueOf<typeof Skins>
|
|
13
|
+
}
|
|
14
|
+
verticalNav: {
|
|
15
|
+
isVerticalNavSemiDark: boolean
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type UserThemeConfig = LayoutConfig & ExplicitThemeConfig
|
|
20
|
+
|
|
21
|
+
// SECTION Custom Input
|
|
22
|
+
export interface CustomInputContent {
|
|
23
|
+
title: string
|
|
24
|
+
desc?: string
|
|
25
|
+
value: string
|
|
26
|
+
subtitle?: string
|
|
27
|
+
icon?: string | object
|
|
28
|
+
images?: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface GridColumn {
|
|
32
|
+
cols?: string
|
|
33
|
+
sm?: string
|
|
34
|
+
md?: string
|
|
35
|
+
lg?: string
|
|
36
|
+
xl?: string
|
|
37
|
+
xxl?: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Data table
|
|
41
|
+
export interface SortItem { key: string; order?: boolean | 'asc' | 'desc' }
|
|
42
|
+
|
|
43
|
+
export interface Options {
|
|
44
|
+
page: number
|
|
45
|
+
itemsPerPage: number
|
|
46
|
+
sortBy: readonly SortItem[]
|
|
47
|
+
groupBy: readonly SortItem[]
|
|
48
|
+
search: string | undefined
|
|
49
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { isToday } from './helpers'
|
|
2
|
+
|
|
3
|
+
export const avatarText = (value: string) => {
|
|
4
|
+
if (!value)
|
|
5
|
+
return ''
|
|
6
|
+
const nameArray = value.split(' ')
|
|
7
|
+
|
|
8
|
+
return nameArray.map(word => word.charAt(0).toUpperCase()).join('')
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// TODO: Try to implement this: https://twitter.com/fireship_dev/status/1565424801216311297
|
|
12
|
+
export const kFormatter = (num: number) => {
|
|
13
|
+
const regex = /\B(?=(\d{3})+(?!\d))/g
|
|
14
|
+
|
|
15
|
+
return Math.abs(num) > 9999 ? `${Math.sign(num) * +((Math.abs(num) / 1000).toFixed(1))}k` : Math.abs(num).toFixed(0).replace(regex, ',')
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Format and return date in Humanize format
|
|
20
|
+
* Intl docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/format
|
|
21
|
+
* Intl Constructor: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat
|
|
22
|
+
* @param {string} value date to format
|
|
23
|
+
* @param {Intl.DateTimeFormatOptions} formatting Intl object to format with
|
|
24
|
+
*/
|
|
25
|
+
export const formatDate = (value: string, formatting: Intl.DateTimeFormatOptions = { month: 'short', day: 'numeric', year: 'numeric' }) => {
|
|
26
|
+
if (!value)
|
|
27
|
+
return value
|
|
28
|
+
|
|
29
|
+
return new Intl.DateTimeFormat('en-US', formatting).format(new Date(value))
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Return short human friendly month representation of date
|
|
34
|
+
* Can also convert date to only time if date is of today (Better UX)
|
|
35
|
+
* @param {string} value date to format
|
|
36
|
+
* @param {boolean} toTimeForCurrentDay Shall convert to time if day is today/current
|
|
37
|
+
*/
|
|
38
|
+
export const formatDateToMonthShort = (value: string, toTimeForCurrentDay = true) => {
|
|
39
|
+
const date = new Date(value)
|
|
40
|
+
let formatting: Record<string, string> = { month: 'short', day: 'numeric' }
|
|
41
|
+
|
|
42
|
+
if (toTimeForCurrentDay && isToday(date))
|
|
43
|
+
formatting = { hour: 'numeric', minute: 'numeric' }
|
|
44
|
+
|
|
45
|
+
return new Intl.DateTimeFormat('en-US', formatting).format(new Date(value))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const prefixWithPlus = (value: number) => value > 0 ? `+${value}` : value
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// 👉 IsEmpty
|
|
2
|
+
export const isEmpty = (value: unknown): boolean => {
|
|
3
|
+
if (value === null || value === undefined || value === '')
|
|
4
|
+
return true
|
|
5
|
+
|
|
6
|
+
return !!(Array.isArray(value) && value.length === 0)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// 👉 IsNullOrUndefined
|
|
10
|
+
export const isNullOrUndefined = (value: unknown): value is undefined | null => {
|
|
11
|
+
return value === null || value === undefined
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// 👉 IsEmptyArray
|
|
15
|
+
export const isEmptyArray = (arr: unknown): boolean => {
|
|
16
|
+
return Array.isArray(arr) && arr.length === 0
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 👉 IsObject
|
|
20
|
+
export const isObject = (obj: unknown): obj is Record<string, unknown> =>
|
|
21
|
+
obj !== null && !!obj && typeof obj === 'object' && !Array.isArray(obj)
|
|
22
|
+
|
|
23
|
+
// 👉 IsToday
|
|
24
|
+
export const isToday = (date: Date) => {
|
|
25
|
+
const today = new Date()
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
date.getDate() === today.getDate()
|
|
29
|
+
&& date.getMonth() === today.getMonth()
|
|
30
|
+
&& date.getFullYear() === today.getFullYear()
|
|
31
|
+
)
|
|
32
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { App } from 'vue'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This is helper function to register plugins like a nuxt
|
|
5
|
+
* To register a plugin just export a const function `defineVuePlugin` that takes `app` as argument and call `app.use`
|
|
6
|
+
* For Scanning plugins it will include all files in `src/plugins` and `src/plugins/**\/index.ts`
|
|
7
|
+
*
|
|
8
|
+
*
|
|
9
|
+
* @param {App} app Vue app instance
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* // File: src/plugins/vuetify/index.ts
|
|
14
|
+
*
|
|
15
|
+
* import type { App } from 'vue'
|
|
16
|
+
* import { createVuetify } from 'vuetify'
|
|
17
|
+
*
|
|
18
|
+
* const vuetify = createVuetify({ ... })
|
|
19
|
+
*
|
|
20
|
+
* export default function (app: App) {
|
|
21
|
+
* app.use(vuetify)
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* All you have to do is use this helper function in `main.ts` file like below:
|
|
26
|
+
* ```ts
|
|
27
|
+
* // File: src/main.ts
|
|
28
|
+
* import { registerPlugins } from '@core/utils/plugins'
|
|
29
|
+
* import { createApp } from 'vue'
|
|
30
|
+
* import App from '@/App.vue'
|
|
31
|
+
*
|
|
32
|
+
* // Create vue app
|
|
33
|
+
* const app = createApp(App)
|
|
34
|
+
*
|
|
35
|
+
* // Register plugins
|
|
36
|
+
* registerPlugins(app) // [!code focus]
|
|
37
|
+
*
|
|
38
|
+
* // Mount vue app
|
|
39
|
+
* app.mount('#app')
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
export const registerPlugins = (app: App) => {
|
|
44
|
+
const imports = import.meta.glob<{ default: (app: App) => void }>(['../../plugins/*.{ts,js}', '../../plugins/*/index.{ts,js}'], { eager: true })
|
|
45
|
+
|
|
46
|
+
const importPaths = Object.keys(imports).sort()
|
|
47
|
+
|
|
48
|
+
importPaths.forEach(path => {
|
|
49
|
+
const pluginImportModule = imports[path]
|
|
50
|
+
|
|
51
|
+
pluginImportModule.default?.(app)
|
|
52
|
+
})
|
|
53
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { isEmpty, isEmptyArray, isNullOrUndefined } from './helpers'
|
|
2
|
+
|
|
3
|
+
// 👉 Required Validator
|
|
4
|
+
export const requiredValidator = (value: unknown) => {
|
|
5
|
+
if (isNullOrUndefined(value) || isEmptyArray(value) || value === false)
|
|
6
|
+
return 'This field is required'
|
|
7
|
+
|
|
8
|
+
return !!String(value).trim().length || 'This field is required'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// 👉 Email Validator
|
|
12
|
+
export const emailValidator = (value: unknown) => {
|
|
13
|
+
if (isEmpty(value))
|
|
14
|
+
return true
|
|
15
|
+
|
|
16
|
+
const re = /^(?:[^<>()[\]\\.,;:\s@"]+(?:\.[^<>()[\]\\.,;:\s@"]+)*|".+")@(?:\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\]|(?:[a-z\-\d]+\.)+[a-z]{2,})$/i
|
|
17
|
+
|
|
18
|
+
if (Array.isArray(value))
|
|
19
|
+
return value.every(val => re.test(String(val))) || 'The Email field must be a valid email'
|
|
20
|
+
|
|
21
|
+
return re.test(String(value)) || 'The Email field must be a valid email'
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// 👉 Password Validator
|
|
25
|
+
export const passwordValidator = (password: string) => {
|
|
26
|
+
const regExp = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%&*()]).{8,}/
|
|
27
|
+
|
|
28
|
+
const validPassword = regExp.test(password)
|
|
29
|
+
|
|
30
|
+
return validPassword || 'Field must contain at least one uppercase, lowercase, special character and digit with min 8 chars'
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// 👉 Confirm Password Validator
|
|
34
|
+
export const confirmedValidator = (value: string, target: string) =>
|
|
35
|
+
|
|
36
|
+
value === target || 'The Confirm Password field confirmation does not match'
|
|
37
|
+
|
|
38
|
+
// 👉 Between Validator
|
|
39
|
+
export const betweenValidator = (value: unknown, min: number, max: number) => {
|
|
40
|
+
const valueAsNumber = Number(value)
|
|
41
|
+
|
|
42
|
+
return (Number(min) <= valueAsNumber && Number(max) >= valueAsNumber) || `Enter number between ${min} and ${max}`
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// 👉 Integer Validator
|
|
46
|
+
export const integerValidator = (value: unknown) => {
|
|
47
|
+
if (isEmpty(value))
|
|
48
|
+
return true
|
|
49
|
+
|
|
50
|
+
if (Array.isArray(value))
|
|
51
|
+
return value.every(val => /^-?\d+$/.test(String(val))) || 'This field must be an integer'
|
|
52
|
+
|
|
53
|
+
return /^-?\d+$/.test(String(value)) || 'This field must be an integer'
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 👉 Regex Validator
|
|
57
|
+
export const regexValidator = (value: unknown, regex: RegExp | string): string | boolean => {
|
|
58
|
+
if (isEmpty(value))
|
|
59
|
+
return true
|
|
60
|
+
|
|
61
|
+
let regeX = regex
|
|
62
|
+
if (typeof regeX === 'string')
|
|
63
|
+
regeX = new RegExp(regeX)
|
|
64
|
+
|
|
65
|
+
if (Array.isArray(value))
|
|
66
|
+
return value.every(val => regexValidator(val, regeX))
|
|
67
|
+
|
|
68
|
+
return regeX.test(String(value)) || 'The Regex field format is invalid'
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 👉 Alpha Validator
|
|
72
|
+
export const alphaValidator = (value: unknown) => {
|
|
73
|
+
if (isEmpty(value))
|
|
74
|
+
return true
|
|
75
|
+
|
|
76
|
+
return /^[A-Z]*$/i.test(String(value)) || 'The Alpha field may only contain alphabetic characters'
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 👉 URL Validator
|
|
80
|
+
export const urlValidator = (value: unknown) => {
|
|
81
|
+
if (isEmpty(value))
|
|
82
|
+
return true
|
|
83
|
+
|
|
84
|
+
const re = /^https?:\/\/[^\s$.?#].\S*$/
|
|
85
|
+
|
|
86
|
+
return re.test(String(value)) || 'URL is invalid'
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 👉 Length Validator
|
|
90
|
+
export const lengthValidator = (value: unknown, length: number) => {
|
|
91
|
+
if (isEmpty(value))
|
|
92
|
+
return true
|
|
93
|
+
|
|
94
|
+
return String(value).length === length || `"The length of the Characters field must be ${length} characters."`
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 👉 Alpha-dash Validator
|
|
98
|
+
export const alphaDashValidator = (value: unknown) => {
|
|
99
|
+
if (isEmpty(value))
|
|
100
|
+
return true
|
|
101
|
+
|
|
102
|
+
const valueAsString = String(value)
|
|
103
|
+
|
|
104
|
+
return /^[\w-]*$/.test(valueAsString) || 'All Character are not valid'
|
|
105
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LiteralUnion } from 'type-fest'
|
|
2
|
+
import { cookieRef } from '@layouts/stores/config'
|
|
3
|
+
|
|
4
|
+
export const resolveVuetifyTheme = (defaultTheme: LiteralUnion<'light' | 'dark' | 'system', string>): 'light' | 'dark' => {
|
|
5
|
+
const cookieColorScheme = cookieRef<'light' | 'dark'>('color-scheme', usePreferredDark().value ? 'dark' : 'light')
|
|
6
|
+
const storedTheme = cookieRef('theme', defaultTheme).value
|
|
7
|
+
|
|
8
|
+
return storedTheme === 'system'
|
|
9
|
+
? cookieColorScheme.value === 'dark'
|
|
10
|
+
? 'dark'
|
|
11
|
+
: 'light'
|
|
12
|
+
: storedTheme as 'light' | 'dark'
|
|
13
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { useToast } from 'vue-toast-notification'
|
|
2
|
+
|
|
3
|
+
export const useAppToasts = (options?: any) => {
|
|
4
|
+
const $toast = useToast()
|
|
5
|
+
const { t } = useI18n()
|
|
6
|
+
|
|
7
|
+
const opt = Object.assign({}, {
|
|
8
|
+
position: 'top-right',
|
|
9
|
+
duration: 3000,
|
|
10
|
+
dismissible: true,
|
|
11
|
+
pauseOnHover: true,
|
|
12
|
+
queue: true,
|
|
13
|
+
}, options)
|
|
14
|
+
|
|
15
|
+
const toastError = (message: string, overrideOption?: any) => {
|
|
16
|
+
const override = Object.assign({}, opt, overrideOption)
|
|
17
|
+
|
|
18
|
+
$toast.error(message, override)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const toastLocalizeError = (key: string, params: any = {}, overrideOption?: any) => {
|
|
22
|
+
const localizeMessage = t(key, params)
|
|
23
|
+
|
|
24
|
+
toastError(localizeMessage, overrideOption)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const toastSuccess = (message: string, overrideOption?: any) => {
|
|
28
|
+
const override = Object.assign({}, opt, overrideOption)
|
|
29
|
+
|
|
30
|
+
$toast.success(message, override)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const toastLocalizeSuccess = (key: string, params: any = {}, overrideOption?: any) => {
|
|
34
|
+
const localizeMessage = t(key, params)
|
|
35
|
+
|
|
36
|
+
toastSuccess(localizeMessage, overrideOption)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
toastError,
|
|
41
|
+
toastLocalizeError,
|
|
42
|
+
toastSuccess,
|
|
43
|
+
toastLocalizeSuccess,
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import type { Country } from '../types/common'
|
|
2
|
+
|
|
3
|
+
export const useValidators = () => {
|
|
4
|
+
const { t } = useI18n()
|
|
5
|
+
|
|
6
|
+
// 👉 Required Validator
|
|
7
|
+
const requiredValidator = (value: unknown) => {
|
|
8
|
+
if (isNullOrUndefined(value) || isEmptyArray(value) || value === false)
|
|
9
|
+
return t('validation.requiredMessage')
|
|
10
|
+
|
|
11
|
+
return !!String(value).trim().length || t('validation.requiredMessage')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// 👉 Email Validator
|
|
15
|
+
const emailValidator = (value: unknown) => {
|
|
16
|
+
if (isEmpty(value))
|
|
17
|
+
return true
|
|
18
|
+
|
|
19
|
+
const re = /^(?:[^<>()[\]\\.,;:\s@"]+(?:\.[^<>()[\]\\.,;:\s@"]+)*|".+")@(?:\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\]|(?:[a-z\-\d]+\.)+[a-z]{2,})$/i
|
|
20
|
+
|
|
21
|
+
if (Array.isArray(value))
|
|
22
|
+
return value.every(val => re.test(String(val))) || t('validation.invalidEmailFormat')
|
|
23
|
+
|
|
24
|
+
return re.test(String(value)) || t('validation.invalidEmailFormat')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 👉 Password Validator
|
|
28
|
+
const passwordValidator = (password: string) => {
|
|
29
|
+
const regExp = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%&*()]).{8,}/
|
|
30
|
+
|
|
31
|
+
const validPassword = regExp.test(password)
|
|
32
|
+
|
|
33
|
+
return validPassword || t('validation.invalidPasswordFormat')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 👉 Confirm Password Validator
|
|
37
|
+
const confirmedPasswordValidator = (value: string, target: string) =>
|
|
38
|
+
|
|
39
|
+
value === target || t('validation.confirmPasswordNotMatch')
|
|
40
|
+
|
|
41
|
+
// 👉 Between Validator
|
|
42
|
+
const betweenValidator = (value: unknown, min: number, max: number) => {
|
|
43
|
+
const valueAsNumber = Number(value)
|
|
44
|
+
|
|
45
|
+
return (Number(min) <= valueAsNumber && Number(max) >= valueAsNumber) || t('validation.betweenMessage', { min, max })
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 👉 Integer Validator
|
|
49
|
+
const integerValidator = (value: unknown) => {
|
|
50
|
+
if (isEmpty(value))
|
|
51
|
+
return true
|
|
52
|
+
|
|
53
|
+
if (Array.isArray(value))
|
|
54
|
+
return value.every(val => /^-?\d+$/.test(String(val))) || t('validation.integerMessage')
|
|
55
|
+
|
|
56
|
+
return /^-?\d+$/.test(String(value)) || t('validation.integerMessage')
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// 👉 Alpha Validator
|
|
60
|
+
const alphaValidator = (value: unknown) => {
|
|
61
|
+
if (isEmpty(value))
|
|
62
|
+
return true
|
|
63
|
+
|
|
64
|
+
return /^[A-Z]*$/i.test(String(value)) || t('validation.alphaMessage')
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 👉 URL Validator
|
|
68
|
+
const urlValidator = (value: unknown) => {
|
|
69
|
+
if (isEmpty(value))
|
|
70
|
+
return true
|
|
71
|
+
|
|
72
|
+
const re = /^https?:\/\/[^\s$.?#].\S*$/
|
|
73
|
+
|
|
74
|
+
return re.test(String(value)) || t('validation.urlMessage')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// 👉 Length Validator
|
|
78
|
+
const lengthValidator = (value: unknown, length: number) => {
|
|
79
|
+
if (isEmpty(value))
|
|
80
|
+
return true
|
|
81
|
+
|
|
82
|
+
return String(value).length === length || t('validation.lengthMessage', { length })
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// 👉 Alpha-dash Validator
|
|
86
|
+
const alphaDashValidator = (value: unknown) => {
|
|
87
|
+
if (isEmpty(value))
|
|
88
|
+
return true
|
|
89
|
+
|
|
90
|
+
const valueAsString = String(value)
|
|
91
|
+
|
|
92
|
+
return /^[\w-]*$/.test(valueAsString) || t('validation.alphaDashMessage')
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const conditionalRequiredValidator = (value: unknown, condition: boolean) => {
|
|
96
|
+
if (!condition)
|
|
97
|
+
return true
|
|
98
|
+
|
|
99
|
+
return requiredValidator(value)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// 👉 mobile Validator
|
|
103
|
+
const mobileValidator = (country: Country | string, value: unknown) => {
|
|
104
|
+
if (isEmpty(value))
|
|
105
|
+
return true
|
|
106
|
+
let countryIso2 = ''
|
|
107
|
+
let autoDialCode = '' // only auto add dialcode when country Object is provided
|
|
108
|
+
if (typeof country === 'string') {
|
|
109
|
+
countryIso2 = country
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
countryIso2 = country.countryCode
|
|
113
|
+
autoDialCode = country.dialCode
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const regex
|
|
117
|
+
= countryIso2.toLocaleLowerCase() === 'my'
|
|
118
|
+
? // malaysia mobile phone
|
|
119
|
+
/^(\+?6?01)[02-46-9]-*\d{7}$|^(\+?6?01)1-*\d{8}$/
|
|
120
|
+
: // other mobile no +919367788755, 8989829304, +16308520397
|
|
121
|
+
/^\+?\(?\d{3}\)?\d{3}[-\s.]?\d{3,8}$/
|
|
122
|
+
|
|
123
|
+
if (Array.isArray(value))
|
|
124
|
+
return value.every(val => regex.test(String(`${autoDialCode}${val}`))) || t('validation.mobileNumberFormat')
|
|
125
|
+
|
|
126
|
+
return regex.test(String(`${autoDialCode}${value}`)) || t('validation.mobileNumberFormat')
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const positiveCurrencyValidator = (value: unknown, mustGreaterZero = false) => {
|
|
130
|
+
if (isEmpty(value))
|
|
131
|
+
return true
|
|
132
|
+
|
|
133
|
+
// /^\d+(\.\d{1,2})?$/
|
|
134
|
+
// eslint-disable-next-line regexp/no-unused-capturing-group
|
|
135
|
+
const regex = /^\d+(\.\d{1,2})?$/
|
|
136
|
+
|
|
137
|
+
const isValidCurrency = regex.test(String(value))
|
|
138
|
+
|
|
139
|
+
const valid = mustGreaterZero && isValidCurrency ? Number(value) > 0 : isValidCurrency
|
|
140
|
+
|
|
141
|
+
return valid || t('validation.currencyFormat')
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
conditionalRequiredValidator,
|
|
146
|
+
mobileValidator,
|
|
147
|
+
requiredValidator,
|
|
148
|
+
emailValidator,
|
|
149
|
+
passwordValidator,
|
|
150
|
+
positiveCurrencyValidator,
|
|
151
|
+
confirmedPasswordValidator,
|
|
152
|
+
betweenValidator,
|
|
153
|
+
integerValidator,
|
|
154
|
+
regexValidator,
|
|
155
|
+
alphaValidator,
|
|
156
|
+
urlValidator,
|
|
157
|
+
lengthValidator,
|
|
158
|
+
alphaDashValidator,
|
|
159
|
+
}
|
|
160
|
+
}
|
|
File without changes
|
|
File without changes
|