@iservice365/layer-common 0.0.1
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/.changeset/README.md +8 -0
- package/.changeset/config.json +11 -0
- package/.editorconfig +12 -0
- package/.github/workflows/main.yml +17 -0
- package/.github/workflows/publish.yml +39 -0
- package/.nuxtrc +1 -0
- package/.playground/app.vue +36 -0
- package/.playground/eslint.config.mjs +6 -0
- package/.playground/nuxt.config.ts +22 -0
- package/CHANGELOG.md +8 -0
- package/README.md +73 -0
- package/app.vue +3 -0
- package/components/BtnUploadFile.vue +139 -0
- package/components/Input/Date.vue +177 -0
- package/components/Input/Password.vue +22 -0
- package/components/InputLabel.vue +18 -0
- package/components/Layout/Header.vue +248 -0
- package/components/Layout/NavigationDrawer.vue +24 -0
- package/components/ListItem.vue +35 -0
- package/components/LocalPagination.vue +31 -0
- package/components/NavigationItem.vue +59 -0
- package/components/PlaceholderComponent.vue +34 -0
- package/components/Snackbar.vue +23 -0
- package/composables/useLocal.ts +41 -0
- package/composables/useLocalAuth.ts +109 -0
- package/composables/useOrg.ts +127 -0
- package/composables/usePermission.ts +54 -0
- package/composables/useRecapPermission.ts +26 -0
- package/composables/useRole.ts +73 -0
- package/composables/useUser.ts +93 -0
- package/composables/useUtils.ts +109 -0
- package/nuxt.config.ts +60 -0
- package/package.json +33 -0
- package/plugins/API.ts +44 -0
- package/plugins/vuetify.ts +41 -0
- package/tsconfig.json +3 -0
- package/types/local.d.ts +63 -0
- package/types/permission.d.ts +24 -0
- package/types/role.d.ts +11 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Changesets
|
|
2
|
+
|
|
3
|
+
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
|
|
4
|
+
with multi-package repos, or single-package repos to help you version and publish your code. You can
|
|
5
|
+
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
|
|
6
|
+
|
|
7
|
+
We have a quick list of common questions to get you started engaging with this project in
|
|
8
|
+
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://unpkg.com/@changesets/config@3.0.5/schema.json",
|
|
3
|
+
"changelog": "@changesets/cli/changelog",
|
|
4
|
+
"commit": false,
|
|
5
|
+
"fixed": [],
|
|
6
|
+
"linked": [],
|
|
7
|
+
"access": "restricted",
|
|
8
|
+
"baseBranch": "main",
|
|
9
|
+
"updateInternalDependencies": "patch",
|
|
10
|
+
"ignore": []
|
|
11
|
+
}
|
package/.editorconfig
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches:
|
|
5
|
+
- "**"
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
- uses: actions/setup-node@v4
|
|
13
|
+
with:
|
|
14
|
+
node-version: 20.x
|
|
15
|
+
cache: "yarn"
|
|
16
|
+
- run: yarn install --frozen-lockfile && yarn dev:prepare
|
|
17
|
+
- run: yarn build
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
on:
|
|
3
|
+
workflow_run:
|
|
4
|
+
workflows: [CI]
|
|
5
|
+
branches: [main]
|
|
6
|
+
types: [completed]
|
|
7
|
+
|
|
8
|
+
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: write
|
|
12
|
+
pull-requests: write
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
publish:
|
|
16
|
+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- uses: actions/setup-node@v4
|
|
22
|
+
with:
|
|
23
|
+
node-version: 20.x
|
|
24
|
+
cache: "yarn" # Use yarn for caching
|
|
25
|
+
cache-dependency-path: yarn.lock # Cache Yarn lockfile
|
|
26
|
+
|
|
27
|
+
- run: yarn install --immutable # Install dependencies with immutable lockfile
|
|
28
|
+
|
|
29
|
+
- name: Create .npmrc for publishing
|
|
30
|
+
run: |
|
|
31
|
+
echo '//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}' > ~/.npmrc
|
|
32
|
+
|
|
33
|
+
- name: Create Release Pull Request or Publish
|
|
34
|
+
id: changesets
|
|
35
|
+
uses: changesets/action@v1
|
|
36
|
+
with:
|
|
37
|
+
publish: yarn release # Use yarn for publishing
|
|
38
|
+
env:
|
|
39
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
package/.nuxtrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
typescript.includeWorkspace = true
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-app>
|
|
3
|
+
<LayoutHeader />
|
|
4
|
+
|
|
5
|
+
<LayoutNavigationDrawer :navigation-items="navigationItems"/>
|
|
6
|
+
|
|
7
|
+
<v-main>
|
|
8
|
+
<slot />
|
|
9
|
+
</v-main>
|
|
10
|
+
</v-app>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
const navigationItems = computed(() => {
|
|
15
|
+
const items: Array<TNavigationItem> = [];
|
|
16
|
+
items.push(
|
|
17
|
+
{
|
|
18
|
+
title: "Create new request",
|
|
19
|
+
route: { name: "index" },
|
|
20
|
+
icon: "mdi-plus",
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
title: "Requests",
|
|
24
|
+
route: { name: "index" },
|
|
25
|
+
icon: "mdi-account-circle",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
title: "Draft",
|
|
29
|
+
route: { name: "index" },
|
|
30
|
+
icon: "mdi-account-circle",
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
return items;
|
|
35
|
+
});
|
|
36
|
+
</script>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export default defineNuxtConfig({
|
|
2
|
+
extends: [".."],
|
|
3
|
+
modules: ["@nuxt/eslint"],
|
|
4
|
+
compatibilityDate: "2024-11-03",
|
|
5
|
+
|
|
6
|
+
runtimeConfig: {
|
|
7
|
+
public: {
|
|
8
|
+
cookieConfig: {
|
|
9
|
+
domain: (process.env.DOMAIN as string) ?? "localhost",
|
|
10
|
+
secure: true,
|
|
11
|
+
maxAge: 30 * 24 * 60 * 60,
|
|
12
|
+
},
|
|
13
|
+
APP_NAME: (process.env.APP_NAME as string) ?? "App",
|
|
14
|
+
APP_NAME_ROUTE: (process.env.APP_NAME_ROUTE as string) ?? "index",
|
|
15
|
+
APP_ACCOUNT: (process.env.APP_ACCOUNT as string) ?? "",
|
|
16
|
+
API_DO_STORAGE_ENDPOINT:
|
|
17
|
+
(process.env.API_DO_STORAGE_ENDPOINT as string) ?? "",
|
|
18
|
+
APP_ADMIN: (process.env.APP_ADMIN as string) ?? "",
|
|
19
|
+
APP_CBA_RECAP: (process.env.APP_CBA_RECAP as string) ?? "",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
});
|
package/CHANGELOG.md
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Nuxt Layer Starter
|
|
2
|
+
|
|
3
|
+
Create Nuxt extendable layer with this GitHub template.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
Make sure to install the dependencies:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm install
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Working on your layer
|
|
14
|
+
|
|
15
|
+
Your layer is at the root of this repository, it is exactly like a regular Nuxt project, except you can publish it on NPM.
|
|
16
|
+
|
|
17
|
+
The `.playground` directory should help you on trying your layer during development.
|
|
18
|
+
|
|
19
|
+
Running `pnpm dev` will prepare and boot `.playground` directory, which imports your layer itself.
|
|
20
|
+
|
|
21
|
+
## Distributing your layer
|
|
22
|
+
|
|
23
|
+
Your Nuxt layer is shaped exactly the same as any other Nuxt project, except you can publish it on NPM.
|
|
24
|
+
|
|
25
|
+
To do so, you only have to check if `files` in `package.json` are valid, then run:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm publish --access public
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Once done, your users will only have to run:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install --save your-layer
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Then add the dependency to their `extends` in `nuxt.config`:
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
defineNuxtConfig({
|
|
41
|
+
extends: 'your-layer'
|
|
42
|
+
})
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Development Server
|
|
46
|
+
|
|
47
|
+
Start the development server on http://localhost:3000
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pnpm dev
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Production
|
|
54
|
+
|
|
55
|
+
Build the application for production:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pnpm build
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Or statically generate it with:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pnpm generate
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Locally preview production build:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pnpm preview
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Checkout the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
package/app.vue
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-input
|
|
3
|
+
:label="label"
|
|
4
|
+
:error="!!errorMessage"
|
|
5
|
+
:error-messages="errorMessage"
|
|
6
|
+
:hide-details="readOnly ?? !!value"
|
|
7
|
+
class="btn-input-file"
|
|
8
|
+
>
|
|
9
|
+
<template #default>
|
|
10
|
+
<v-row no-gutters>
|
|
11
|
+
<v-col v-if="value || readOnly" cols="12">
|
|
12
|
+
<v-row no-gutters>
|
|
13
|
+
<v-card
|
|
14
|
+
variant="outlined"
|
|
15
|
+
border="thin"
|
|
16
|
+
class="px-4 text-caption font-weight-medium"
|
|
17
|
+
:rounded="readOnly ? '' : '0 s'"
|
|
18
|
+
height="36"
|
|
19
|
+
@click="emit('click:view')"
|
|
20
|
+
>
|
|
21
|
+
<v-row no-gutters class="fill-height" align="center">
|
|
22
|
+
{{ value ? "View attachment" : "No file attached" }}
|
|
23
|
+
</v-row>
|
|
24
|
+
</v-card>
|
|
25
|
+
<v-card
|
|
26
|
+
v-if="!readOnly"
|
|
27
|
+
variant="outlined"
|
|
28
|
+
border="s-0 thin"
|
|
29
|
+
rounded="0 e"
|
|
30
|
+
class="px-4 d-inline"
|
|
31
|
+
height="36"
|
|
32
|
+
@click="emit('click:close')"
|
|
33
|
+
>
|
|
34
|
+
<v-row no-gutters class="fill-height" align="center">
|
|
35
|
+
<v-icon size="small"> mdi-close </v-icon>
|
|
36
|
+
</v-row>
|
|
37
|
+
</v-card>
|
|
38
|
+
</v-row>
|
|
39
|
+
</v-col>
|
|
40
|
+
|
|
41
|
+
<v-col v-else cols="12">
|
|
42
|
+
<v-btn
|
|
43
|
+
variant="outlined"
|
|
44
|
+
border="thin"
|
|
45
|
+
class="text-none"
|
|
46
|
+
:prepend-icon="value ? '' : 'mdi-tray-arrow-up'"
|
|
47
|
+
:disabled="loading"
|
|
48
|
+
:loading="loading"
|
|
49
|
+
@click="selectAttachment"
|
|
50
|
+
>
|
|
51
|
+
Add file
|
|
52
|
+
</v-btn>
|
|
53
|
+
</v-col>
|
|
54
|
+
</v-row>
|
|
55
|
+
|
|
56
|
+
<v-file-input
|
|
57
|
+
v-show="false"
|
|
58
|
+
v-model="attachment"
|
|
59
|
+
multiple
|
|
60
|
+
accept="image/*"
|
|
61
|
+
:class="`attachment-input-${inputClass}`"
|
|
62
|
+
:name="name + 'custom-input-file'"
|
|
63
|
+
@change="uploadAttachment"
|
|
64
|
+
/>
|
|
65
|
+
</template>
|
|
66
|
+
</v-input>
|
|
67
|
+
</template>
|
|
68
|
+
|
|
69
|
+
<script setup lang="ts">
|
|
70
|
+
const value = defineModel<string>({ required: true, default: "" });
|
|
71
|
+
const attachment = ref<File | null>(null);
|
|
72
|
+
const loading = ref(false);
|
|
73
|
+
|
|
74
|
+
const emit = defineEmits(["click:view", "click:close", "upload"]);
|
|
75
|
+
|
|
76
|
+
const { addFile } = useFile();
|
|
77
|
+
const inputClass = Date.now().toString();
|
|
78
|
+
|
|
79
|
+
function selectAttachment() {
|
|
80
|
+
const input = document.querySelector(
|
|
81
|
+
`.attachment-input-${inputClass} input`
|
|
82
|
+
) as HTMLInputElement;
|
|
83
|
+
input.click();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function uploadAttachment(e: Event) {
|
|
87
|
+
loading.value = true;
|
|
88
|
+
const files = (e.target as HTMLInputElement).files;
|
|
89
|
+
|
|
90
|
+
if (files && files.length > 0) {
|
|
91
|
+
const file = files[0];
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
const res = await addFile(file);
|
|
95
|
+
value.value = res.id as string;
|
|
96
|
+
await emit("upload", res);
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.log(error);
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
console.log("No file selected");
|
|
102
|
+
}
|
|
103
|
+
loading.value = false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Other props (optional)
|
|
107
|
+
const { label, rules, name, readOnly } = defineProps({
|
|
108
|
+
label: {
|
|
109
|
+
type: String,
|
|
110
|
+
default: "Rating",
|
|
111
|
+
},
|
|
112
|
+
// Array of validation functions: (number) => true | string
|
|
113
|
+
rules: {
|
|
114
|
+
type: Array<Function>,
|
|
115
|
+
default: () => [],
|
|
116
|
+
},
|
|
117
|
+
name: {
|
|
118
|
+
type: String,
|
|
119
|
+
required: true,
|
|
120
|
+
default: "button-upload-file",
|
|
121
|
+
},
|
|
122
|
+
readOnly: {
|
|
123
|
+
type: Boolean,
|
|
124
|
+
default: false,
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Compute the first failed validation rule, if any.
|
|
130
|
+
* Each rule returns true (if valid) or a string (if invalid).
|
|
131
|
+
*/
|
|
132
|
+
const errorMessage = computed(() => {
|
|
133
|
+
for (const rule of rules) {
|
|
134
|
+
const result = rule(attachment.value || value.value);
|
|
135
|
+
return typeof result === "string" ? result : null;
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
138
|
+
});
|
|
139
|
+
</script>
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-input
|
|
3
|
+
:error="!!validationErrMsg"
|
|
4
|
+
:error-messages="validationErrMsg"
|
|
5
|
+
hide-details="auto"
|
|
6
|
+
:name="name + 'custom-input-date'"
|
|
7
|
+
:disabled="props.disabled"
|
|
8
|
+
>
|
|
9
|
+
<template #default>
|
|
10
|
+
<v-row>
|
|
11
|
+
<v-col cols="12" lg="6" md="6">
|
|
12
|
+
<v-select
|
|
13
|
+
v-model="month"
|
|
14
|
+
:items="props.months"
|
|
15
|
+
label="Month"
|
|
16
|
+
density="comfortable"
|
|
17
|
+
:name="props.name + 'custom-input-date-month'"
|
|
18
|
+
hide-details
|
|
19
|
+
:error="!!validationErrMsg"
|
|
20
|
+
:disabled="props.disabled"
|
|
21
|
+
/>
|
|
22
|
+
</v-col>
|
|
23
|
+
|
|
24
|
+
<v-col cols="12" lg="3" md="3">
|
|
25
|
+
<v-text-field
|
|
26
|
+
v-model.number="day"
|
|
27
|
+
type="number"
|
|
28
|
+
label="Day"
|
|
29
|
+
hide-details
|
|
30
|
+
placeholder="DD"
|
|
31
|
+
density="comfortable"
|
|
32
|
+
:name="props.name + 'custom-input-date-day'"
|
|
33
|
+
:error="!!validationErrMsg"
|
|
34
|
+
:disabled="props.disabled"
|
|
35
|
+
/>
|
|
36
|
+
</v-col>
|
|
37
|
+
|
|
38
|
+
<v-col cols="12" lg="3" md="3">
|
|
39
|
+
<v-text-field
|
|
40
|
+
v-model.number="year"
|
|
41
|
+
type="number"
|
|
42
|
+
label="Year"
|
|
43
|
+
hide-details
|
|
44
|
+
placeholder="YYYY"
|
|
45
|
+
density="comfortable"
|
|
46
|
+
:name="props.name + 'custom-input-date-year'"
|
|
47
|
+
:error="!!validationErrMsg"
|
|
48
|
+
:disabled="props.disabled"
|
|
49
|
+
/>
|
|
50
|
+
</v-col>
|
|
51
|
+
</v-row>
|
|
52
|
+
</template>
|
|
53
|
+
</v-input>
|
|
54
|
+
</template>
|
|
55
|
+
|
|
56
|
+
<script setup lang="ts">
|
|
57
|
+
const month = defineModel("month", { default: "" });
|
|
58
|
+
const day = defineModel("day", { default: 0 });
|
|
59
|
+
const year = defineModel("year", { default: 0 });
|
|
60
|
+
|
|
61
|
+
const props = defineProps({
|
|
62
|
+
months: {
|
|
63
|
+
type: Array,
|
|
64
|
+
default: [
|
|
65
|
+
"January",
|
|
66
|
+
"February",
|
|
67
|
+
"March",
|
|
68
|
+
"April",
|
|
69
|
+
"May",
|
|
70
|
+
"June",
|
|
71
|
+
"July",
|
|
72
|
+
"August",
|
|
73
|
+
"September",
|
|
74
|
+
"October",
|
|
75
|
+
"November",
|
|
76
|
+
"December",
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
name: {
|
|
80
|
+
type: String,
|
|
81
|
+
default: "input-date-combo",
|
|
82
|
+
},
|
|
83
|
+
disabled: {
|
|
84
|
+
type: Boolean,
|
|
85
|
+
default: false,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const isLeapYear = (year: number): boolean =>
|
|
90
|
+
(year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
|
91
|
+
|
|
92
|
+
const monthMap: Record<string, number> = {
|
|
93
|
+
January: 1,
|
|
94
|
+
February: 2,
|
|
95
|
+
March: 3,
|
|
96
|
+
April: 4,
|
|
97
|
+
May: 5,
|
|
98
|
+
June: 6,
|
|
99
|
+
July: 7,
|
|
100
|
+
August: 8,
|
|
101
|
+
September: 9,
|
|
102
|
+
October: 10,
|
|
103
|
+
November: 11,
|
|
104
|
+
December: 12,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const validateBirthDate = (): string => {
|
|
108
|
+
const _month = monthMap[month.value];
|
|
109
|
+
const _day = day.value;
|
|
110
|
+
const _year = year.value;
|
|
111
|
+
|
|
112
|
+
const errorMessage = "Enter a valid date";
|
|
113
|
+
|
|
114
|
+
if (
|
|
115
|
+
!_month ||
|
|
116
|
+
!_day ||
|
|
117
|
+
!_year ||
|
|
118
|
+
_year < 1904 ||
|
|
119
|
+
_year > new Date().getFullYear()
|
|
120
|
+
) {
|
|
121
|
+
return errorMessage;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const daysInMonth = [
|
|
125
|
+
31,
|
|
126
|
+
isLeapYear(_year) ? 29 : 28,
|
|
127
|
+
31,
|
|
128
|
+
30,
|
|
129
|
+
31,
|
|
130
|
+
30,
|
|
131
|
+
31,
|
|
132
|
+
31,
|
|
133
|
+
30,
|
|
134
|
+
31,
|
|
135
|
+
30,
|
|
136
|
+
31,
|
|
137
|
+
];
|
|
138
|
+
|
|
139
|
+
if (_day < 1 || _day > daysInMonth[_month - 1]) {
|
|
140
|
+
return errorMessage;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!_month || !_day || !_year) {
|
|
144
|
+
return errorMessage;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return "";
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const validationErrMsg = ref("");
|
|
151
|
+
|
|
152
|
+
const date = computed(() => {
|
|
153
|
+
return {
|
|
154
|
+
day: day.value,
|
|
155
|
+
month: month.value,
|
|
156
|
+
year: year.value,
|
|
157
|
+
};
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
validationErrMsg.value = validateBirthDate();
|
|
161
|
+
|
|
162
|
+
const disabled = computed(() => props.disabled);
|
|
163
|
+
|
|
164
|
+
watch(disabled, (curr) => {
|
|
165
|
+
if (curr) {
|
|
166
|
+
validationErrMsg.value = validateBirthDate();
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
watch(
|
|
171
|
+
date,
|
|
172
|
+
() => {
|
|
173
|
+
validationErrMsg.value = validateBirthDate();
|
|
174
|
+
},
|
|
175
|
+
{ deep: true }
|
|
176
|
+
);
|
|
177
|
+
</script>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-text-field
|
|
3
|
+
id="_password"
|
|
4
|
+
v-model="password"
|
|
5
|
+
:type="showPassword ? 'text' : 'password'"
|
|
6
|
+
:append-inner-icon="showPassword ? 'mdi-eye-off' : 'mdi-eye'"
|
|
7
|
+
v-bind="$attrs"
|
|
8
|
+
autocomplete="off"
|
|
9
|
+
@click:append-inner="togglePasswordVisibility"
|
|
10
|
+
/>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
// Define the props for the v-model
|
|
15
|
+
const password = defineModel({ default: "" });
|
|
16
|
+
|
|
17
|
+
// Control password visibility
|
|
18
|
+
const showPassword = ref(false);
|
|
19
|
+
const togglePasswordVisibility = () => {
|
|
20
|
+
showPassword.value = !showPassword.value;
|
|
21
|
+
};
|
|
22
|
+
</script>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<span class="text-subtitle-2 font-weight-medium">
|
|
3
|
+
{{ title }} <span v-if="props.required" class="text-error">*</span>
|
|
4
|
+
</span>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup lang="ts">
|
|
8
|
+
const props = defineProps({
|
|
9
|
+
title: {
|
|
10
|
+
type: String,
|
|
11
|
+
required: true,
|
|
12
|
+
},
|
|
13
|
+
required: {
|
|
14
|
+
type: Boolean,
|
|
15
|
+
default: false,
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
</script>
|