@finema/finework-layer 1.0.17 → 1.0.18

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,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.0.18](https://gitlab.finema.co/finema/finework/finework-frontend-layer/compare/1.0.17...1.0.18) (2026-03-23)
4
+
5
+ ### Bug Fixes
6
+
7
+ * refactor PortalApp layout for improved structure and responsiveness ([ec69707](https://gitlab.finema.co/finema/finework/finework-frontend-layer/commit/ec697075d2125b87985d90474b26885073522202))
8
+
3
9
  ## [1.0.17](https://gitlab.finema.co/finema/finework/finework-frontend-layer/compare/1.0.16...1.0.17) (2026-03-23)
4
10
 
5
11
  ### Bug Fixes
@@ -1,257 +1,275 @@
1
1
  <template>
2
- <Card
3
- v-if="dailyApps.length > 0 || managementApps.length > 0 || financeApps.length > 0 || peopleApps.length > 0 || legalApps.length > 0"
4
- :ui="{
5
- body: isNavbar ? 'max-h-[calc(100vh-95px)] md:max-h-[calc(100vh-115px)] overflow-auto' : 'h-full overflow-auto',
6
- }"
7
- >
8
- <div
9
- class="bg-white"
10
- >
11
- <div class="mb-5 flex items-center gap-2">
12
- <img
13
- src="/icon-finema.png"
14
- alt="icon-finema"
15
- class="h-8 w-8 -translate-y-1"
16
- />
17
- <div class="text-2xl font-bold">
18
- Finework Apps
2
+ <DefineTemplate>
3
+ <div class="space-y-6">
4
+ <div
5
+ v-if="dailyApps.length > 0"
6
+ class="space-y-5"
7
+ >
8
+ <div class="text-lg font-bold text-gray-600">
9
+ Daily work Apps
19
10
  </div>
20
- </div>
21
-
22
- <div class="space-y-6">
23
11
  <div
24
- v-if="dailyApps.length > 0"
25
- class="space-y-5"
12
+ class="grid"
13
+ :class="[isNavbar ?`gap-5 md:grid-cols-2 xl:grid-cols-4` : `grid-cols-1 gap-2`]"
26
14
  >
27
- <div class="text-lg font-bold text-gray-600">
28
- Daily work Apps
29
- </div>
30
- <div
31
- class="grid"
32
- :class="[isNavbar ?`gap-5 md:grid-cols-2 xl:grid-cols-4` : `grid-cols-1 gap-2`]"
15
+ <component
16
+ :is="app.status === StatusPortal.DEVELOPING ? 'div' : NuxtLink"
17
+ v-for="app in dailyApps"
18
+ :key="app.name"
19
+ :to="app.status !== StatusPortal.DEVELOPING ? app.to : undefined"
20
+ class="relative flex items-center gap-3 rounded-lg px-2.5 py-[15px]"
21
+ :class="app.status === StatusPortal.DEVELOPING
22
+ ? 'cursor-not-allowed bg-gray-200 opacity-60'
23
+ : 'bg-gray-100 hover:bg-gray-200'"
24
+ @click="app.status !== StatusPortal.DEVELOPING && handleLinkClick(app.to)"
33
25
  >
34
- <component
35
- :is="app.status === StatusPortal.DEVELOPING ? 'div' : NuxtLink"
36
- v-for="app in dailyApps"
37
- :key="app.name"
38
- :to="app.status !== StatusPortal.DEVELOPING ? app.to : undefined"
39
- class="relative flex items-center gap-3 rounded-lg px-2.5 py-[15px]"
40
- :class="app.status === StatusPortal.DEVELOPING
41
- ? 'cursor-not-allowed bg-gray-200 opacity-60'
42
- : 'bg-gray-100 hover:bg-gray-200'"
43
- @click="app.status !== StatusPortal.DEVELOPING && handleLinkClick(app.to)"
26
+ <div
27
+ v-if="app.status === StatusPortal.DEVELOPING"
28
+ class="absolute top-2 right-2 rounded-full bg-orange-100 px-2 py-0.5 text-xs font-semibold text-orange-600"
44
29
  >
45
- <div
46
- v-if="app.status === StatusPortal.DEVELOPING"
47
- class="absolute top-2 right-2 rounded-full bg-orange-100 px-2 py-0.5 text-xs font-semibold text-orange-600"
48
- >
49
- กำลังพัฒนา
30
+ กำลังพัฒนา
31
+ </div>
32
+ <img
33
+ :src="app.logo"
34
+ :alt="app.label"
35
+ class="h-[45px] w-[45px] bg-white"
36
+ />
37
+ <div>
38
+ <div class="text-lg font-bold">
39
+ {{ app.label }}
50
40
  </div>
51
- <img
52
- :src="app.logo"
53
- :alt="app.label"
54
- class="h-[45px] w-[45px] bg-white"
55
- />
56
- <div>
57
- <div class="text-lg font-bold">
58
- {{ app.label }}
59
- </div>
60
- <div class="text-sm text-gray-500">
61
- {{ app.description }}
62
- </div>
41
+ <div class="text-sm text-gray-500">
42
+ {{ app.description }}
63
43
  </div>
64
- </component>
65
- </div>
44
+ </div>
45
+ </component>
46
+ </div>
47
+ </div>
48
+ <div
49
+ v-if="managementApps.length > 0"
50
+ class="space-y-5"
51
+ >
52
+ <div class="text-lg font-bold text-gray-600">
53
+ Management
66
54
  </div>
67
55
  <div
68
- v-if="managementApps.length > 0"
69
- class="space-y-5"
56
+ class="grid"
57
+ :class="[isNavbar ?`gap-5 md:grid-cols-2 xl:grid-cols-4` : `grid-cols-1 gap-2`]"
70
58
  >
71
- <div class="text-lg font-bold text-gray-600">
72
- Management
73
- </div>
74
- <div
75
- class="grid"
76
- :class="[isNavbar ?`gap-5 md:grid-cols-2 xl:grid-cols-4` : `grid-cols-1 gap-2`]"
59
+ <component
60
+ :is="app.status === StatusPortal.DEVELOPING ? 'div' : NuxtLink"
61
+ v-for="app in managementApps"
62
+ :key="app.name"
63
+ :to="app.status !== StatusPortal.DEVELOPING ? app.to : undefined"
64
+ class="relative flex items-center gap-3 rounded-lg px-2.5 py-[15px]"
65
+ :class="app.status === StatusPortal.DEVELOPING
66
+ ? 'cursor-not-allowed bg-gray-200 opacity-60'
67
+ : 'bg-gray-100 hover:bg-gray-200'"
68
+ @click="app.status !== StatusPortal.DEVELOPING && handleLinkClick(app.to)"
77
69
  >
78
- <component
79
- :is="app.status === StatusPortal.DEVELOPING ? 'div' : NuxtLink"
80
- v-for="app in managementApps"
81
- :key="app.name"
82
- :to="app.status !== StatusPortal.DEVELOPING ? app.to : undefined"
83
- class="relative flex items-center gap-3 rounded-lg px-2.5 py-[15px]"
84
- :class="app.status === StatusPortal.DEVELOPING
85
- ? 'cursor-not-allowed bg-gray-200 opacity-60'
86
- : 'bg-gray-100 hover:bg-gray-200'"
87
- @click="app.status !== StatusPortal.DEVELOPING && handleLinkClick(app.to)"
70
+ <div
71
+ v-if="app.status === StatusPortal.DEVELOPING"
72
+ class="absolute top-2 right-2 rounded-full bg-orange-100 px-2 py-0.5 text-xs font-semibold text-orange-600"
88
73
  >
89
- <div
90
- v-if="app.status === StatusPortal.DEVELOPING"
91
- class="absolute top-2 right-2 rounded-full bg-orange-100 px-2 py-0.5 text-xs font-semibold text-orange-600"
92
- >
93
- กำลังพัฒนา
74
+ กำลังพัฒนา
75
+ </div>
76
+ <img
77
+ :src="app.logo"
78
+ :alt="app.label"
79
+ class="h-[45px] w-[45px] bg-white"
80
+ />
81
+ <div>
82
+ <div class="text-lg font-bold">
83
+ {{ app.label }}
94
84
  </div>
95
- <img
96
- :src="app.logo"
97
- :alt="app.label"
98
- class="h-[45px] w-[45px] bg-white"
99
- />
100
- <div>
101
- <div class="text-lg font-bold">
102
- {{ app.label }}
103
- </div>
104
- <div class="text-sm text-gray-500">
105
- {{ app.description }}
106
- </div>
85
+ <div class="text-sm text-gray-500">
86
+ {{ app.description }}
107
87
  </div>
108
- </component>
109
- </div>
88
+ </div>
89
+ </component>
110
90
  </div>
91
+ </div>
111
92
 
93
+ <div
94
+ v-if="financeApps.length > 0"
95
+ class="space-y-5"
96
+ >
97
+ <div class="text-lg font-bold text-gray-600">
98
+ Finance
99
+ </div>
112
100
  <div
113
- v-if="financeApps.length > 0"
114
- class="space-y-5"
101
+ class="grid"
102
+ :class="[isNavbar ?`gap-5 md:grid-cols-2 xl:grid-cols-4` : `grid-cols-1 gap-2`]"
115
103
  >
116
- <div class="text-lg font-bold text-gray-600">
117
- Finance
118
- </div>
119
- <div
120
- class="grid"
121
- :class="[isNavbar ?`gap-5 md:grid-cols-2 xl:grid-cols-4` : `grid-cols-1 gap-2`]"
104
+ <component
105
+ :is="app.status === StatusPortal.DEVELOPING ? 'div' : NuxtLink"
106
+ v-for="app in financeApps"
107
+ :key="app.name"
108
+ :to="app.status !== StatusPortal.DEVELOPING ? app.to : undefined"
109
+ class="relative flex items-center gap-3 rounded-lg px-2.5 py-[15px]"
110
+ :class="app.status === StatusPortal.DEVELOPING
111
+ ? 'cursor-not-allowed bg-gray-200 opacity-60'
112
+ : 'bg-gray-100 hover:bg-gray-200'"
113
+ @click="app.status !== StatusPortal.DEVELOPING && handleLinkClick(app.to)"
122
114
  >
123
- <component
124
- :is="app.status === StatusPortal.DEVELOPING ? 'div' : NuxtLink"
125
- v-for="app in financeApps"
126
- :key="app.name"
127
- :to="app.status !== StatusPortal.DEVELOPING ? app.to : undefined"
128
- class="relative flex items-center gap-3 rounded-lg px-2.5 py-[15px]"
129
- :class="app.status === StatusPortal.DEVELOPING
130
- ? 'cursor-not-allowed bg-gray-200 opacity-60'
131
- : 'bg-gray-100 hover:bg-gray-200'"
132
- @click="app.status !== StatusPortal.DEVELOPING && handleLinkClick(app.to)"
115
+ <div
116
+ v-if="app.status === StatusPortal.DEVELOPING"
117
+ class="absolute top-2 right-2 rounded-full bg-orange-100 px-2 py-0.5 text-xs font-semibold text-orange-600"
133
118
  >
134
- <div
135
- v-if="app.status === StatusPortal.DEVELOPING"
136
- class="absolute top-2 right-2 rounded-full bg-orange-100 px-2 py-0.5 text-xs font-semibold text-orange-600"
137
- >
138
- กำลังพัฒนา
139
- </div>
119
+ กำลังพัฒนา
120
+ </div>
140
121
 
141
- <img
142
- :src="app.logo"
143
- :alt="app.label"
144
- class="h-[45px] w-[45px] bg-white"
145
- />
122
+ <img
123
+ :src="app.logo"
124
+ :alt="app.label"
125
+ class="h-[45px] w-[45px] bg-white"
126
+ />
146
127
 
147
- <div>
148
- <div class="text-lg font-bold">
149
- {{ app.label }}
150
- </div>
151
- <div class="text-sm text-gray-500">
152
- {{ app.description }}
153
- </div>
128
+ <div>
129
+ <div class="text-lg font-bold">
130
+ {{ app.label }}
154
131
  </div>
155
- </component>
156
- </div>
132
+ <div class="text-sm text-gray-500">
133
+ {{ app.description }}
134
+ </div>
135
+ </div>
136
+ </component>
157
137
  </div>
138
+ </div>
158
139
 
140
+ <div
141
+ v-if="peopleApps.length >0"
142
+ class="space-y-5"
143
+ >
144
+ <div class="text-lg font-bold text-gray-600">
145
+ People
146
+ </div>
159
147
  <div
160
- v-if="peopleApps.length >0"
161
- class="space-y-5"
148
+ class="grid"
149
+ :class="[isNavbar ?`gap-5 md:grid-cols-2 xl:grid-cols-4` : `grid-cols-1 gap-2`]"
162
150
  >
163
- <div class="text-lg font-bold text-gray-600">
164
- People
165
- </div>
166
- <div
167
- class="grid"
168
- :class="[isNavbar ?`gap-5 md:grid-cols-2 xl:grid-cols-4` : `grid-cols-1 gap-2`]"
151
+ <component
152
+ :is="app.status === StatusPortal.DEVELOPING ? 'div' : NuxtLink"
153
+ v-for="app in peopleApps"
154
+ :key="app.name"
155
+ :to="app.status !== StatusPortal.DEVELOPING ? app.to : undefined"
156
+ class="relative flex items-center gap-3 rounded-lg px-2.5 py-[15px]"
157
+ :class="app.status === StatusPortal.DEVELOPING
158
+ ? 'cursor-not-allowed bg-gray-200 opacity-60'
159
+ : 'bg-gray-100 hover:bg-gray-200'"
160
+ @click="app.status !== StatusPortal.DEVELOPING && handleLinkClick(app.to)"
169
161
  >
170
- <component
171
- :is="app.status === StatusPortal.DEVELOPING ? 'div' : NuxtLink"
172
- v-for="app in peopleApps"
173
- :key="app.name"
174
- :to="app.status !== StatusPortal.DEVELOPING ? app.to : undefined"
175
- class="relative flex items-center gap-3 rounded-lg px-2.5 py-[15px]"
176
- :class="app.status === StatusPortal.DEVELOPING
177
- ? 'cursor-not-allowed bg-gray-200 opacity-60'
178
- : 'bg-gray-100 hover:bg-gray-200'"
179
- @click="app.status !== StatusPortal.DEVELOPING && handleLinkClick(app.to)"
162
+ <div
163
+ v-if="app.status === StatusPortal.DEVELOPING"
164
+ class="absolute top-2 right-2 rounded-full bg-orange-100 px-2 py-0.5 text-xs font-semibold text-orange-600"
180
165
  >
181
- <div
182
- v-if="app.status === StatusPortal.DEVELOPING"
183
- class="absolute top-2 right-2 rounded-full bg-orange-100 px-2 py-0.5 text-xs font-semibold text-orange-600"
184
- >
185
- กำลังพัฒนา
166
+ กำลังพัฒนา
167
+ </div>
168
+ <img
169
+ :src="app.logo"
170
+ :alt="app.label"
171
+ class="h-[45px] w-[45px] bg-white"
172
+ />
173
+ <div>
174
+ <div class="text-lg font-bold">
175
+ {{ app.label }}
186
176
  </div>
187
- <img
188
- :src="app.logo"
189
- :alt="app.label"
190
- class="h-[45px] w-[45px] bg-white"
191
- />
192
- <div>
193
- <div class="text-lg font-bold">
194
- {{ app.label }}
195
- </div>
196
- <div class="text-sm text-gray-500">
197
- {{ app.description }}
198
- </div>
177
+ <div class="text-sm text-gray-500">
178
+ {{ app.description }}
199
179
  </div>
200
- </component>
201
- </div>
180
+ </div>
181
+ </component>
202
182
  </div>
183
+ </div>
203
184
 
185
+ <div
186
+ v-if="legalApps.length > 0"
187
+ class="space-y-5"
188
+ >
189
+ <div class="text-lg font-bold text-gray-600">
190
+ Legal
191
+ </div>
204
192
  <div
205
- v-if="legalApps.length > 0"
206
- class="space-y-5"
193
+ class="grid"
194
+ :class="[isNavbar ?`gap-5 md:grid-cols-2 xl:grid-cols-4` : `grid-cols-1 gap-2`]"
207
195
  >
208
- <div class="text-lg font-bold text-gray-600">
209
- Legal
210
- </div>
211
- <div
212
- class="grid"
213
- :class="[isNavbar ?`gap-5 md:grid-cols-2 xl:grid-cols-4` : `grid-cols-1 gap-2`]"
196
+ <component
197
+ :is="app.status === StatusPortal.DEVELOPING ? 'div' : NuxtLink"
198
+ v-for="app in legalApps"
199
+ :key="app.name"
200
+ :to="app.status !== StatusPortal.DEVELOPING ? app.to : undefined"
201
+ class="relative flex items-center gap-3 rounded-lg px-2.5 py-[15px]"
202
+ :class="app.status === StatusPortal.DEVELOPING
203
+ ? 'cursor-not-allowed bg-gray-200 opacity-60'
204
+ : 'bg-gray-100 hover:bg-gray-200'"
205
+ @click="app.status !== StatusPortal.DEVELOPING && handleLinkClick(app.to)"
214
206
  >
215
- <component
216
- :is="app.status === StatusPortal.DEVELOPING ? 'div' : NuxtLink"
217
- v-for="app in legalApps"
218
- :key="app.name"
219
- :to="app.status !== StatusPortal.DEVELOPING ? app.to : undefined"
220
- class="relative flex items-center gap-3 rounded-lg px-2.5 py-[15px]"
221
- :class="app.status === StatusPortal.DEVELOPING
222
- ? 'cursor-not-allowed bg-gray-200 opacity-60'
223
- : 'bg-gray-100 hover:bg-gray-200'"
224
- @click="app.status !== StatusPortal.DEVELOPING && handleLinkClick(app.to)"
207
+ <div
208
+ v-if="app.status === StatusPortal.DEVELOPING"
209
+ class="absolute top-2 right-2 rounded-full bg-orange-100 px-2 py-0.5 text-xs font-semibold text-orange-600"
225
210
  >
226
- <div
227
- v-if="app.status === StatusPortal.DEVELOPING"
228
- class="absolute top-2 right-2 rounded-full bg-orange-100 px-2 py-0.5 text-xs font-semibold text-orange-600"
229
- >
230
- กำลังพัฒนา
211
+ กำลังพัฒนา
212
+ </div>
213
+ <img
214
+ :src="app.logo"
215
+ :alt="app.label"
216
+ class="h-[45px] w-[45px] bg-white"
217
+ />
218
+ <div>
219
+ <div class="text-lg font-bold">
220
+ {{ app.label }}
231
221
  </div>
232
- <img
233
- :src="app.logo"
234
- :alt="app.label"
235
- class="h-[45px] w-[45px] bg-white"
236
- />
237
- <div>
238
- <div class="text-lg font-bold">
239
- {{ app.label }}
240
- </div>
241
- <div class="text-sm text-gray-500">
242
- {{ app.description }}
243
- </div>
222
+ <div class="text-sm text-gray-500">
223
+ {{ app.description }}
244
224
  </div>
245
- </component>
246
- </div>
225
+ </div>
226
+ </component>
247
227
  </div>
248
228
  </div>
249
229
  </div>
230
+ </DefineTemplate>
231
+ <Card
232
+ v-if="dailyApps.length > 0 || managementApps.length > 0 || financeApps.length > 0 || peopleApps.length > 0 || legalApps.length > 0"
233
+ :ui="{
234
+ body: isNavbar
235
+ ? 'max-h-[calc(100vh-95px)] md:max-h-[calc(100vh-115px)] overflow-auto'
236
+ : 'h-full overflow-auto p-4!',
237
+ }"
238
+ >
239
+ <div class="bg-white">
240
+ <Collapsible
241
+ default-open
242
+ >
243
+ <div class="flex items-center justify-between gap-4">
244
+ <div class="mb-5 flex items-center gap-2">
245
+ <img
246
+ src="/icon-finema.png"
247
+ alt="icon-finema"
248
+ class="h-8 w-8 -translate-y-1"
249
+ />
250
+ <div class="text-2xl font-bold">
251
+ Finework Apps
252
+ </div>
253
+ </div>
254
+
255
+ <Button
256
+ v-if="!isNavbar"
257
+ variant="outline"
258
+ :icon="open ? 'i-lucide-chevron-up' : 'i-lucide-chevron-down'"
259
+ />
260
+ </div>
261
+ <template #content>
262
+ <ReuseTemplate />
263
+ </template>
264
+ </Collapsible>
265
+ <ReuseTemplate v-if="isNavbar" />
266
+ </div>
250
267
  </Card>
251
268
  </template>
252
269
 
253
270
  <script lang="ts" setup>
254
271
  import { resolveComponent } from 'vue'
272
+ import { createReusableTemplate } from '@vueuse/core'
255
273
 
256
274
  const emit = defineEmits<{
257
275
  (e: 'close'): void
@@ -268,6 +286,8 @@ const enum StatusPortal {
268
286
  const NuxtLink = resolveComponent('NuxtLink')
269
287
  const auth = useAuth()
270
288
  const route = useRoute()
289
+ const open = ref(true)
290
+ const [DefineTemplate, ReuseTemplate] = createReusableTemplate()
271
291
 
272
292
  const handleLinkClick = (to: string) => {
273
293
  if (route.path === to) {
@@ -381,7 +401,7 @@ const financeApps = computed(() => [
381
401
  logo: '/admin/cost-sheet.png',
382
402
  label: 'Cost Sheet',
383
403
  description: 'รายรับรายจ่ายงบประมาณโครงการ',
384
- to: routes.costSheet.docs.doc.to,
404
+ to: routes.costSheet.overview.to,
385
405
  status: StatusPortal.ACTIVE,
386
406
  },
387
407
  ]
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@finema/finework-layer",
3
3
  "type": "module",
4
- "version": "1.0.17",
4
+ "version": "1.0.18",
5
5
  "main": "./nuxt.config.ts",
6
6
  "scripts": {
7
7
  "dev": "nuxi dev .playground -o",