@finema/finework-layer 0.2.82 → 0.2.83

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.83](https://gitlab.finema.co/finema/finework/finework-frontend-layer/compare/0.2.82...0.2.83) (2025-12-16)
4
+
5
+ ### Features
6
+
7
+ * add slideover component and enhance app layout with new routes and permissions ([bb1eac6](https://gitlab.finema.co/finema/finework/finework-frontend-layer/commit/bb1eac63e24536e2ca9bc0f5cba4da19a1663885))
8
+ * refactor Apps component to use PortalApp for better structure and maintainability ([cbaf2bf](https://gitlab.finema.co/finema/finework/finework-frontend-layer/commit/cbaf2bff9fe14ca3961c74493535784a5072310e))
9
+
10
+ ### Bug Fixes
11
+
12
+ * add permision ([a45466b](https://gitlab.finema.co/finema/finework/finework-frontend-layer/commit/a45466b7366ff89b1f4c37f038ee68c332300c0b))
13
+ * employee ([9f2968b](https://gitlab.finema.co/finema/finework/finework-frontend-layer/commit/9f2968b3fd08f2910e926baa4cd59b4c9f03e229))
14
+
3
15
  ## [0.2.82](https://gitlab.finema.co/finema/finework/finework-frontend-layer/compare/0.2.81...0.2.82) (2025-12-09)
4
16
 
5
17
  ### Bug Fixes
package/app/app.config.ts CHANGED
@@ -33,7 +33,7 @@ export default defineAppConfig({
33
33
  tabs: {
34
34
  slots: {
35
35
  list: 'p-0 ',
36
- label: ' font-bold ',
36
+ label: ' font-bold',
37
37
  leadingIcon: 'hover:!text-primary',
38
38
  },
39
39
  variants: {
@@ -140,5 +140,33 @@ export default defineAppConfig({
140
140
  },
141
141
  ],
142
142
  },
143
+ slideover: {
144
+ variants: {
145
+ side: {
146
+ top: {
147
+ content: 'inset-x-0 top-0 max-h-full',
148
+ },
149
+ },
150
+ },
151
+ compoundVariants: [
152
+ {
153
+ transition: true,
154
+ side: 'top',
155
+ class: {
156
+ content: 'data-[state=open]:animate-[slide-in-from-top_200ms_ease-in-out] data-[state=closed]:animate-[slide-out-to-top_200ms_ease-in-out]',
157
+ },
158
+ },
159
+ {
160
+ transition: false,
161
+ side: 'top',
162
+ class: {
163
+ content:
164
+ 'data-[state=open]:animate-[slideInTop_300ms_ease-in-out] '
165
+ + 'data-[state=closed]:animate-[slideOutTop_300ms_ease-in-out]',
166
+ },
167
+ },
168
+
169
+ ],
170
+ },
143
171
  },
144
172
  })
@@ -75,4 +75,15 @@
75
75
 
76
76
  body {
77
77
  @apply bg-[var(--color-background)];
78
- }
78
+ }
79
+
80
+ @keyframes slideInTop {
81
+ from { transform: translateY(-20px); opacity: 0; }
82
+ to { transform: translateY(0); opacity: 1; }
83
+ }
84
+
85
+ @keyframes slideOutTop {
86
+ from { transform: translateY(0); opacity: 1; }
87
+ to { transform: translateY(-20px); opacity: 0; }
88
+ }
89
+
@@ -1,45 +1,25 @@
1
1
  <template>
2
- <Popover
3
- :content="{
4
- align: 'center',
5
- side: 'bottom',
6
- sideOffset: 8,
7
- }"
8
- >
9
- <Button
10
- icon="mingcute:dot-grid-line"
11
- variant="ghost"
12
- class="text-gray-500"
13
- />
14
-
15
- <template #content>
16
- <Card class="w-[300px]">
17
- <div
18
- class="grid grid-cols-3 gap-6"
19
- >
20
- <Button
21
- v-for="item in auth.menusNavbar.value"
22
- :key="item.to"
23
- class="flex flex-col items-center p-0 text-center"
24
- variant="link"
25
- :to="item.to"
26
- >
27
- <div class="flex h-[42px] items-center justify-center">
28
- <img
29
- :src="item.icon"
30
- class="h-auto w-[32px]"
31
- />
32
- </div>
33
- <span class="text-sm font-medium text-gray-700">
34
- {{ item.label }}
35
- </span>
36
- </Button>
37
- </div>
38
- </Card>
39
- </template>
40
- </Popover>
2
+ <div class="">
3
+ <Slideover
4
+ side="top"
5
+ :portal="true"
6
+ :modal="false"
7
+ class="w-full"
8
+ :transition="false"
9
+ :ui="{ content: 'lg:translate-y-[63px] w-full lg:translate-y-[71px]' }"
10
+ >
11
+ <Button
12
+ icon="mingcute:dot-grid-line"
13
+ variant="ghost"
14
+ class="text-gray-500"
15
+ />
16
+ <template #content>
17
+ <PortalApp />
18
+ </template>
19
+ </Slideover>
20
+ </div>
41
21
  </template>
42
22
 
43
23
  <script lang="ts" setup>
44
- const auth = useAuth()
24
+
45
25
  </script>
@@ -0,0 +1,279 @@
1
+ <template>
2
+ <div class="max-h-[calc(100vh-80px)] overflow-auto bg-white p-5">
3
+ <div class="mb-5 flex items-center gap-2">
4
+ <img
5
+ src="/icon-finema.png"
6
+ alt="icon-finema"
7
+ class="h-8 w-8 -translate-y-1"
8
+ />
9
+ <div class="text-2xl font-bold">
10
+ Finework Apps
11
+ </div>
12
+
13
+ <Button
14
+ icon="i-heroicons-x-mark-20-solid"
15
+ variant="ghost"
16
+ class="ml-auto"
17
+ />
18
+ </div>
19
+ <div class="grid gap-5 md:grid-cols-2 lg:grid-cols-3">
20
+ <div
21
+ v-if="managementApps.length > 0"
22
+ class="space-y-6"
23
+ >
24
+ <div class="text-lg font-bold text-gray-600">
25
+ Management
26
+ </div>
27
+
28
+ <NuxtLink
29
+ v-for="app in managementApps"
30
+ :key="app.name"
31
+ :to="app.to"
32
+ class="flex items-center gap-3 rounded-lg bg-gray-100 px-2.5 py-[15px]"
33
+ >
34
+ <img
35
+ :src="app.logo"
36
+ :alt="app.label"
37
+ class="h-[45px] w-[45px] rounded-sm bg-white"
38
+ />
39
+ <div>
40
+ <div class="text-lg font-bold">{{ app.label }}</div>
41
+ <div class="text-sm text-gray-500">{{ app.description }}</div>
42
+ </div>
43
+ </NuxtLink>
44
+ </div>
45
+
46
+ <div
47
+ v-if="financeApps.length > 0"
48
+ class="space-y-6"
49
+ >
50
+ <div class="text-lg font-bold text-gray-600">
51
+ Finance
52
+ </div>
53
+
54
+ <NuxtLink
55
+ v-for="app in financeApps"
56
+ :key="app.name"
57
+ :to="app.to"
58
+ class="flex items-center gap-3 rounded-lg bg-gray-100 px-2.5 py-[15px]"
59
+ >
60
+ <img
61
+ :src="app.logo"
62
+ :alt="app.label"
63
+ class="h-[45px] w-[45px] rounded-sm bg-white"
64
+ />
65
+ <div>
66
+ <div class="text-lg font-bold">{{ app.label }}</div>
67
+ <div class="text-sm text-gray-500">{{ app.description }}</div>
68
+ </div>
69
+ </NuxtLink>
70
+ </div>
71
+
72
+ <div
73
+ v-if="peopleApps.length >0"
74
+ class="space-y-6"
75
+ >
76
+ <div class="text-lg font-bold text-gray-600">
77
+ People
78
+ </div>
79
+
80
+ <NuxtLink
81
+ v-for="app in peopleApps"
82
+ :key="app.name"
83
+ :to="app.to"
84
+ class="flex items-center gap-3 rounded-lg bg-gray-100 px-2.5 py-[15px]"
85
+ >
86
+ <img
87
+ :src="app.logo"
88
+ :alt="app.label"
89
+ class="h-[45px] w-[45px] rounded-sm bg-white"
90
+ />
91
+ <div>
92
+ <div class="text-lg font-bold">{{ app.label }}</div>
93
+ <div class="text-sm text-gray-500">{{ app.description }}</div>
94
+ </div>
95
+ </NuxtLink>
96
+ </div>
97
+
98
+ <div
99
+ v-if="legalApps.length > 0"
100
+ class="space-y-6"
101
+ >
102
+ <div class="text-lg font-bold text-gray-600">
103
+ Legal
104
+ </div>
105
+
106
+ <NuxtLink
107
+ v-for="app in legalApps"
108
+ :key="app.name"
109
+ :to="app.to"
110
+ class="flex items-center gap-3 rounded-lg bg-gray-100 px-2.5 py-[15px]"
111
+ >
112
+ <img
113
+ :src="app.logo"
114
+ :alt="app.label"
115
+ class="h-[45px] w-[45px] rounded-sm bg-white"
116
+ />
117
+ <div>
118
+ <div class="text-lg font-bold">{{ app.label }}</div>
119
+ <div class="text-sm text-gray-500">{{ app.description }}</div>
120
+ </div>
121
+ </NuxtLink>
122
+ </div>
123
+ </div>
124
+ </div>
125
+ </template>
126
+
127
+ <script lang="ts" setup>
128
+ const auth = useAuth()
129
+ const managementApps = computed(() => [
130
+ ...(auth.hasPermission(
131
+ UserModule.PMO,
132
+ Permission.ADMIN,
133
+ Permission.USER,
134
+ Permission.SUPER,
135
+ )
136
+ ? [
137
+ {
138
+ name: 'pmo',
139
+ logo: '/admin/pmo-logo.png',
140
+ label: 'PMO',
141
+ description: 'จัดระเบียบและบริหารโครงการของคุณ',
142
+ to: routes.pmo.project.projects.to,
143
+ },
144
+ ]
145
+ : []),
146
+ // ...(auth.hasPermission(UserModule.REQUEST, Permission.USER)
147
+ // ? [
148
+ // {
149
+ // name: 'request',
150
+ // logo: '/admin/request-admin.png',
151
+ // label: 'Requests',
152
+ // description: 'จัดการคำขอ',
153
+ // to: '',
154
+ // },
155
+ // ]
156
+ // : []),
157
+ ...(auth.hasPermission(UserModule.CHECKIN, Permission.ADMIN)
158
+ ? [
159
+ {
160
+ name: 'clockin-admin',
161
+ logo: '/admin/clock-in-admin-logo.png',
162
+ label: 'Clock-in Report',
163
+ description: 'รายงานการลงเวลา',
164
+ to: routes.adminClockin.checkinDashboard.to,
165
+ },
166
+ ]
167
+ : []),
168
+
169
+ ...(auth.hasPermission(UserModule.TIMESHEET, Permission.ADMIN, Permission.SUPER)
170
+ ? [
171
+ {
172
+ name: 'timesheet-admin',
173
+ logo: '/admin/timesheet-admin-logo.png',
174
+ label: 'Timesheet Report',
175
+ description: 'รายงานการบันทึกข้อมูลไทม์ชีท',
176
+ to: routes.adminTimesheet.summaryReport.to,
177
+ },
178
+ ]
179
+ : []),
180
+ ...(auth.hasPermission(UserModule.TODO, Permission.USER, Permission.ADMIN)
181
+ ? [
182
+ {
183
+ name: 'todo',
184
+ logo: '/admin/todo.png',
185
+ label: 'TODO',
186
+ description: 'ระบบจัดการงานที่ต้องทำ',
187
+ to: routes.todo.to,
188
+ },
189
+ ]
190
+ : []),
191
+
192
+ ])
193
+
194
+ const financeApps = computed(() => [
195
+ // ...(auth.hasPermission(UserModule.EFACTORING, Permission.USER)
196
+ // ? [
197
+ // {
198
+ // name: 'eFactoring',
199
+ // logo: '/admin/efactoring.png',
200
+ // label: 'eFactoring',
201
+ // description: 'การเบิกเงินหมุนเวียนกับธนาคาร',
202
+ // to: routes.costSheet.overview.to,
203
+ // },
204
+ // ]
205
+ // : []),
206
+ ...(auth.hasPermission(UserModule.COSTSHEET, Permission.USER, Permission.ADMIN)
207
+ ? [
208
+ {
209
+ name: 'Cost Sheet',
210
+ logo: '/admin/cost-sheet.png',
211
+ label: 'Cost Sheet',
212
+ description: 'รายรับรายจ่ายงบประมาณโครงการ',
213
+ to: routes.costSheet.to,
214
+ },
215
+ ]
216
+ : []),
217
+ // ...(auth.hasPermission(UserModule.COSTSHEET, Permission.USER)
218
+ // ? [
219
+ // {
220
+ // name: 'Guarantee',
221
+ // logo: '/admin/cost-sheet.png',
222
+ // label: 'งบค้ำประกัน',
223
+ // description: 'การเบิกเงินค้ำซองและค้ำสัญญากับธนาคาร',
224
+ // to: routes.costSheet.overview.to,
225
+ // },
226
+ // ]
227
+ // : []),
228
+ ...(auth.hasPermission(UserModule.QUOTATION, Permission.USER, Permission.ADMIN)
229
+ ? [
230
+ {
231
+ name: 'Quotation',
232
+ logo: '/admin/quotation.png',
233
+ label: 'Quotation',
234
+ description: 'รายรับรายจ่ายงบประมาณโครงการ',
235
+ to: routes.quotation.to,
236
+ },
237
+ ]
238
+ : []),
239
+ ])
240
+
241
+ const peopleApps = computed(() => [
242
+ ...(auth.hasPermission(UserModule.EMPLOYEE, Permission.USER, Permission.ADMIN)
243
+ ? [
244
+ {
245
+ name: 'Employee',
246
+ logo: '/admin/employee.png',
247
+ label: 'Employee',
248
+ description: 'ระบบจัดการข้อมูลพนักงาน',
249
+ to: routes.employee.to,
250
+ },
251
+ ]
252
+ : []),
253
+ ...(auth.hasPermission(UserModule.NEWSLETTER, Permission.USER, Permission.ADMIN)
254
+ ? [
255
+ {
256
+ name: 'Newsletter',
257
+ logo: '/admin/newsletter.png',
258
+ label: 'Newsletter',
259
+ description: 'ระบบจัดการข่าวสาร',
260
+ to: routes.newsletter.to,
261
+ },
262
+ ]
263
+ : []),
264
+ ])
265
+
266
+ const legalApps = computed(() => [
267
+ ...(auth.hasPermission(UserModule.CONTRACT, Permission.USER, Permission.ADMIN)
268
+ ? [
269
+ {
270
+ name: 'Contract',
271
+ logo: '/admin/contract.png',
272
+ label: 'Contract',
273
+ description: 'สร้างและจัดการสัญญา',
274
+ to: routes.legal.to,
275
+ },
276
+ ]
277
+ : []),
278
+ ])
279
+ </script>
@@ -49,14 +49,38 @@ export enum UserModule {
49
49
  PMO = 'pmo',
50
50
  TIMESHEET = 'timesheet',
51
51
  SETTING = 'setting',
52
+ QUOTATION = 'quotation',
53
+ COSTSHEET = 'costsheet',
54
+ NEWSLETTER = 'newsletter',
55
+ CONTRACT = 'contract',
56
+ REQUEST = 'request',
57
+ TODO = 'todo',
58
+ EVALUATION = 'evaluation',
59
+ EMPLOYEE = 'employee',
60
+ ASSET = 'asset',
61
+ RECRUIT = 'recruit',
62
+ BIDBOND = 'bidbond',
63
+ EFACTORING = 'efactoring',
52
64
  }
53
65
 
54
66
  export interface IUserAccessLevel {
55
67
  used_id: string
56
68
  pmo: Permission.USER | Permission.ADMIN | Permission.SUPER
57
69
  clockin: Permission.USER | Permission.ADMIN
58
- timesheet: Permission.USER | Permission.ADMIN
70
+ timesheet: Permission.USER | Permission.ADMIN | Permission.SUPER
59
71
  setting: Permission.USER | Permission.SUPER
72
+ quotation: Permission
73
+ costsheet: Permission
74
+ newsletter: Permission
75
+ contract: Permission
76
+ request: Permission
77
+ todo: Permission
78
+ evaluation: Permission
79
+ employee: Permission
80
+ asset: Permission
81
+ recruit: Permission
82
+ bidbond: Permission
83
+ efactoring: Permission
60
84
  }
61
85
 
62
86
  export const useAuth = () => {
@@ -82,5 +82,29 @@ export const routes = {
82
82
  },
83
83
  },
84
84
  },
85
+ costSheet: {
86
+ label: 'Cost Sheet',
87
+ to: '/cost-sheet/',
88
+ },
89
+ legal: {
90
+ label: 'Legal',
91
+ to: '/legal/',
92
+ },
93
+ quotation: {
94
+ label: 'Quotation',
95
+ to: '/quotation/',
96
+ },
97
+ newsletter: {
98
+ label: 'Newsletter',
99
+ to: '/newsletter/',
100
+ },
101
+ todo: {
102
+ label: 'To Do',
103
+ to: '/todo/',
104
+ },
105
+ employee: {
106
+ label: 'Employee',
107
+ to: '/employee/',
108
+ },
85
109
 
86
110
  } as const
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@finema/finework-layer",
3
3
  "type": "module",
4
- "version": "0.2.82",
4
+ "version": "0.2.83",
5
5
  "main": "./nuxt.config.ts",
6
6
  "scripts": {
7
7
  "dev": "nuxi dev .playground -o",