@devappsnpm/vue-kit 0.1.0

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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +82 -0
  3. package/bin/devapps-vue.js +3 -0
  4. package/dist/index.cjs +556 -0
  5. package/dist/index.cjs.map +1 -0
  6. package/dist/index.js +510 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/ui.cjs +515 -0
  9. package/dist/ui.cjs.map +1 -0
  10. package/dist/ui.js +485 -0
  11. package/dist/ui.js.map +1 -0
  12. package/package.json +57 -0
  13. package/stubs/components/component.vue.stub +17 -0
  14. package/stubs/module/basic/component.vue.stub +9 -0
  15. package/stubs/module/basic/index.ts.stub +1 -0
  16. package/stubs/module/crud/modal/components/DeleteModal.vue.stub +35 -0
  17. package/stubs/module/crud/modal/components/FormModal.vue.stub +88 -0
  18. package/stubs/module/crud/modal/components/List.vue.stub +60 -0
  19. package/stubs/module/crud/modal/index.ts.stub +4 -0
  20. package/stubs/module/crud/modal/router.ts.stub +11 -0
  21. package/stubs/module/crud/modal/services/service.ts.stub +9 -0
  22. package/stubs/module/crud/modal/stores/store.ts.stub +9 -0
  23. package/stubs/module/crud/modal/types/types.ts.stub +16 -0
  24. package/stubs/module/crud/modal/views/View.vue.stub +83 -0
  25. package/stubs/module/crud/page/components/DeleteModal.vue.stub +35 -0
  26. package/stubs/module/crud/page/components/Form.vue.stub +62 -0
  27. package/stubs/module/crud/page/components/List.vue.stub +42 -0
  28. package/stubs/module/crud/page/index.ts.stub +4 -0
  29. package/stubs/module/crud/page/pages/CreatePage.vue.stub +27 -0
  30. package/stubs/module/crud/page/pages/EditPage.vue.stub +34 -0
  31. package/stubs/module/crud/page/pages/ListPage.vue.stub +59 -0
  32. package/stubs/module/crud/page/pages/ShowPage.vue.stub +28 -0
  33. package/stubs/module/crud/page/router.ts.stub +26 -0
  34. package/stubs/module/crud/page/services/service.ts.stub +9 -0
  35. package/stubs/module/crud/page/stores/store.ts.stub +9 -0
  36. package/stubs/module/crud/page/types/types.ts.stub +16 -0
  37. package/stubs/module/dashboard/Dashboard.vue.stub +24 -0
  38. package/stubs/module/dashboard/index.ts.stub +1 -0
  39. package/stubs/module/dashboard/router.ts.stub +11 -0
  40. package/stubs/module/resource/List.vue.stub +19 -0
  41. package/stubs/module/resource/index.ts.stub +3 -0
  42. package/stubs/module/resource/service.ts.stub +9 -0
  43. package/stubs/module/resource/store.ts.stub +9 -0
  44. package/stubs/module/resource/types.ts.stub +10 -0
  45. package/stubs/pages/page.vue.stub +14 -0
  46. package/stubs/services/service.ts.stub +13 -0
  47. package/stubs/stores/store.ts.stub +19 -0
  48. package/stubs/types/types.ts.stub +6 -0
@@ -0,0 +1 @@
1
+ export * from './components/{{ ModuleName }}Component.vue'
@@ -0,0 +1,35 @@
1
+ <script setup lang="ts">
2
+ import { ConfirmDeleteModal } from '@devapps/vue-kit/ui'
3
+ import { use{{ ModuleName }}Store } from '../stores/{{ moduleSlug }}.store'
4
+ import type { {{ ModuleName }} } from '../types/{{ moduleSlug }}.types'
5
+
6
+ const props = defineProps<{
7
+ open: boolean
8
+ item: {{ ModuleName }} | null
9
+ }>()
10
+
11
+ const emit = defineEmits<{
12
+ close: []
13
+ deleted: []
14
+ }>()
15
+
16
+ const store = use{{ ModuleName }}Store()
17
+
18
+ async function handleConfirm() {
19
+ if (!props.item) return
20
+ await store.remove(props.item.uuid)
21
+ emit('deleted')
22
+ }
23
+ </script>
24
+
25
+ <template>
26
+ <ConfirmDeleteModal
27
+ :open="open"
28
+ title="Delete {{ ModuleName }}"
29
+ description="This action cannot be undone. Please type the identifier to confirm."
30
+ :confirmation-label="item?.uuid ?? ''"
31
+ :loading="store.deleting"
32
+ @close="emit('close')"
33
+ @confirm="handleConfirm"
34
+ />
35
+ </template>
@@ -0,0 +1,88 @@
1
+ <script setup lang="ts">
2
+ import { reactive, watch } from 'vue'
3
+ import { BaseModal } from '@devapps/vue-kit/ui'
4
+ import { Form } from '@devapps/vue-kit'
5
+ import { use{{ ModuleName }}Store } from '../stores/{{ moduleSlug }}.store'
6
+ import type { {{ ModuleName }}, {{ ModuleName }}Form } from '../types/{{ moduleSlug }}.types'
7
+
8
+ const props = defineProps<{
9
+ open: boolean
10
+ item?: {{ ModuleName }} | null
11
+ }>()
12
+
13
+ const emit = defineEmits<{
14
+ close: []
15
+ saved: []
16
+ }>()
17
+
18
+ const store = use{{ ModuleName }}Store()
19
+
20
+ const form = reactive(
21
+ new Form<{{ ModuleName }}Form>({
22
+ // TODO: initialise form fields
23
+ }),
24
+ )
25
+
26
+ watch(
27
+ () => props.item,
28
+ (item) => {
29
+ if (item) {
30
+ // TODO: populate form from item
31
+ // Object.assign(form.data, { field: item.field })
32
+ } else {
33
+ form.reset()
34
+ }
35
+ },
36
+ { immediate: true },
37
+ )
38
+
39
+ async function handleSubmit() {
40
+ await form.submit(async (data) => {
41
+ if (props.item) {
42
+ await store.update(props.item.uuid, data)
43
+ } else {
44
+ await store.create(data)
45
+ }
46
+ emit('saved')
47
+ })
48
+ }
49
+ </script>
50
+
51
+ <template>
52
+ <BaseModal
53
+ :open="open"
54
+ :loading="form.processing"
55
+ @close="emit('close')"
56
+ >
57
+ <template #header>
58
+ <h2 class="text-lg font-semibold">
59
+ {{ item ? 'Edit' : 'Create' }} {{ ModuleName }}
60
+ </h2>
61
+ </template>
62
+
63
+ <form id="{{ moduleSlug }}-form" class="space-y-4" @submit.prevent="handleSubmit">
64
+ <!-- TODO: add form fields -->
65
+ </form>
66
+
67
+ <template #footer>
68
+ <div class="flex justify-end gap-2">
69
+ <button
70
+ type="button"
71
+ class="px-4 py-2 rounded border text-sm"
72
+ :disabled="form.processing"
73
+ @click="emit('close')"
74
+ >
75
+ Cancel
76
+ </button>
77
+ <button
78
+ type="submit"
79
+ form="{{ moduleSlug }}-form"
80
+ class="px-4 py-2 rounded bg-blue-600 text-white text-sm disabled:opacity-50"
81
+ :disabled="form.processing"
82
+ >
83
+ {{ form.processing ? 'Saving...' : 'Save' }}
84
+ </button>
85
+ </div>
86
+ </template>
87
+ </BaseModal>
88
+ </template>
@@ -0,0 +1,60 @@
1
+ <script setup lang="ts">
2
+ import type { {{ ModuleName }} } from '../types/{{ moduleSlug }}.types'
3
+
4
+ const emit = defineEmits<{
5
+ edit: [item: {{ ModuleName }}]
6
+ delete: [item: {{ ModuleName }}]
7
+ }>()
8
+
9
+ defineProps<{
10
+ items: {{ ModuleName }}[]
11
+ loading?: boolean
12
+ }>()
13
+ </script>
14
+
15
+ <template>
16
+ <div class="{{ moduleSlug }}-list">
17
+ <div v-if="loading" class="flex justify-center py-8">
18
+ <span class="text-gray-500">Loading...</span>
19
+ </div>
20
+
21
+ <table v-else class="w-full text-sm">
22
+ <thead>
23
+ <tr class="border-b text-left text-gray-500">
24
+ <th class="pb-2">UUID</th>
25
+ <!-- TODO: add columns -->
26
+ <th class="pb-2 text-right">Actions</th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ <tr
31
+ v-for="item in items"
32
+ :key="item.uuid"
33
+ class="border-b hover:bg-gray-50"
34
+ >
35
+ <td class="py-2 font-mono text-xs">{{ item.uuid }}</td>
36
+ <!-- TODO: add cells -->
37
+ <td class="py-2 text-right space-x-2">
38
+ <button
39
+ class="text-blue-600 hover:underline text-xs"
40
+ @click="emit('edit', item)"
41
+ >
42
+ Edit
43
+ </button>
44
+ <button
45
+ class="text-red-600 hover:underline text-xs"
46
+ @click="emit('delete', item)"
47
+ >
48
+ Delete
49
+ </button>
50
+ </td>
51
+ </tr>
52
+ <tr v-if="items.length === 0">
53
+ <td colspan="3" class="py-8 text-center text-gray-400">
54
+ No records found.
55
+ </td>
56
+ </tr>
57
+ </tbody>
58
+ </table>
59
+ </div>
60
+ </template>
@@ -0,0 +1,4 @@
1
+ export * from './types/{{ moduleSlug }}.types'
2
+ export * from './services/{{ moduleSlug }}.service'
3
+ export * from './stores/{{ moduleSlug }}.store'
4
+ export { default as routes } from './router'
@@ -0,0 +1,11 @@
1
+ import type { RouteRecordRaw } from 'vue-router'
2
+
3
+ const routes: RouteRecordRaw[] = [
4
+ {
5
+ path: '/{{ moduleSlugPlural }}',
6
+ name: '{{ moduleSlugPlural }}.index',
7
+ component: () => import('./views/{{ ModuleName }}View.vue'),
8
+ },
9
+ ]
10
+
11
+ export default routes
@@ -0,0 +1,9 @@
1
+ import { CrudService } from '@devapps/vue-kit'
2
+ import type { HttpClient } from '@devapps/vue-kit'
3
+ import type { {{ ModuleName }} } from '../types/{{ moduleSlug }}.types'
4
+
5
+ export class {{ ModuleName }}Service extends CrudService<{{ ModuleName }}> {
6
+ constructor(http: HttpClient) {
7
+ super(http, '{{ resourcePath }}')
8
+ }
9
+ }
@@ -0,0 +1,9 @@
1
+ import { defineCrudStore } from '@devapps/vue-kit'
2
+ import { {{ ModuleName }}Service } from '../services/{{ moduleSlug }}.service'
3
+ import type { {{ ModuleName }} } from '../types/{{ moduleSlug }}.types'
4
+ import { useHttpClient } from '@/composables/useHttpClient' // adjust to your project
5
+
6
+ export const use{{ ModuleName }}Store = defineCrudStore<{{ ModuleName }}>(
7
+ '{{ moduleName }}',
8
+ () => new {{ ModuleName }}Service(useHttpClient()),
9
+ )
@@ -0,0 +1,16 @@
1
+ export interface {{ ModuleName }} {
2
+ uuid: string
3
+ // TODO: add fields
4
+ created_at: string
5
+ updated_at: string
6
+ }
7
+
8
+ export interface {{ ModuleName }}Form {
9
+ // TODO: add form fields
10
+ }
11
+
12
+ export interface {{ ModuleName }}Filters {
13
+ page?: number
14
+ per_page?: number
15
+ search?: string
16
+ }
@@ -0,0 +1,83 @@
1
+ <script setup lang="ts">
2
+ import { ref, onMounted } from 'vue'
3
+ import { use{{ ModuleName }}Store } from '../stores/{{ moduleSlug }}.store'
4
+ import {{ ModuleName }}List from '../components/{{ ModuleName }}List.vue'
5
+ import {{ ModuleName }}FormModal from '../components/{{ ModuleName }}FormModal.vue'
6
+ import {{ ModuleName }}DeleteModal from '../components/{{ ModuleName }}DeleteModal.vue'
7
+ import type { {{ ModuleName }} } from '../types/{{ moduleSlug }}.types'
8
+
9
+ const store = use{{ ModuleName }}Store()
10
+
11
+ const isFormModalOpen = ref(false)
12
+ const isDeleteModalOpen = ref(false)
13
+ const selected{{ ModuleName }} = ref<{{ ModuleName }} | null>(null)
14
+ const {{ moduleName }}ToDelete = ref<{{ ModuleName }} | null>(null)
15
+
16
+ onMounted(() => loadItems())
17
+
18
+ async function loadItems(page = store.pagination?.currentPage ?? 1) {
19
+ await store.fetchAll({ page })
20
+ }
21
+
22
+ function handleCreate() {
23
+ selected{{ ModuleName }}.value = null
24
+ isFormModalOpen.value = true
25
+ }
26
+
27
+ async function handleEdit(item: {{ ModuleName }}) {
28
+ await store.fetchOne(item.uuid)
29
+ selected{{ ModuleName }}.value = store.item
30
+ isFormModalOpen.value = true
31
+ }
32
+
33
+ function handleDelete(item: {{ ModuleName }}) {
34
+ {{ moduleName }}ToDelete.value = item
35
+ isDeleteModalOpen.value = true
36
+ }
37
+
38
+ function handleFormSaved() {
39
+ isFormModalOpen.value = false
40
+ loadItems()
41
+ }
42
+
43
+ function handleDeleted() {
44
+ isDeleteModalOpen.value = false
45
+ {{ moduleName }}ToDelete.value = null
46
+ loadItems()
47
+ }
48
+ </script>
49
+
50
+ <template>
51
+ <div class="{{ moduleSlug }}-view">
52
+ <div class="flex items-center justify-between mb-4">
53
+ <h1 class="text-xl font-semibold">{{ ModuleNamePlural }}</h1>
54
+ <button
55
+ class="px-4 py-2 bg-blue-600 text-white rounded text-sm"
56
+ @click="handleCreate"
57
+ >
58
+ New {{ ModuleName }}
59
+ </button>
60
+ </div>
61
+
62
+ <{{ ModuleName }}List
63
+ :items="store.items"
64
+ :loading="store.loading"
65
+ @edit="handleEdit"
66
+ @delete="handleDelete"
67
+ />
68
+
69
+ <{{ ModuleName }}FormModal
70
+ :open="isFormModalOpen"
71
+ :item="selected{{ ModuleName }}"
72
+ @close="isFormModalOpen = false"
73
+ @saved="handleFormSaved"
74
+ />
75
+
76
+ <{{ ModuleName }}DeleteModal
77
+ :open="isDeleteModalOpen"
78
+ :item="{{ moduleName }}ToDelete"
79
+ @close="isDeleteModalOpen = false"
80
+ @deleted="handleDeleted"
81
+ />
82
+ </div>
83
+ </template>
@@ -0,0 +1,35 @@
1
+ <script setup lang="ts">
2
+ import { ConfirmDeleteModal } from '@devapps/vue-kit/ui'
3
+ import { use{{ ModuleName }}Store } from '../stores/{{ moduleSlug }}.store'
4
+ import type { {{ ModuleName }} } from '../types/{{ moduleSlug }}.types'
5
+
6
+ const props = defineProps<{
7
+ open: boolean
8
+ item: {{ ModuleName }} | null
9
+ }>()
10
+
11
+ const emit = defineEmits<{
12
+ close: []
13
+ deleted: []
14
+ }>()
15
+
16
+ const store = use{{ ModuleName }}Store()
17
+
18
+ async function handleConfirm() {
19
+ if (!props.item) return
20
+ await store.remove(props.item.uuid)
21
+ emit('deleted')
22
+ }
23
+ </script>
24
+
25
+ <template>
26
+ <ConfirmDeleteModal
27
+ :open="open"
28
+ title="Delete {{ ModuleName }}"
29
+ description="This action cannot be undone. Please type the identifier to confirm."
30
+ :confirmation-label="item?.uuid ?? ''"
31
+ :loading="store.deleting"
32
+ @close="emit('close')"
33
+ @confirm="handleConfirm"
34
+ />
35
+ </template>
@@ -0,0 +1,62 @@
1
+ <script setup lang="ts">
2
+ import { reactive, watch } from 'vue'
3
+ import { Form } from '@devapps/vue-kit'
4
+ import type { {{ ModuleName }}, {{ ModuleName }}Form } from '../types/{{ moduleSlug }}.types'
5
+
6
+ const props = defineProps<{
7
+ item?: {{ ModuleName }} | null
8
+ loading?: boolean
9
+ }>()
10
+
11
+ const emit = defineEmits<{
12
+ submit: [data: {{ ModuleName }}Form]
13
+ cancel: []
14
+ }>()
15
+
16
+ const form = reactive(
17
+ new Form<{{ ModuleName }}Form>({
18
+ // TODO: initialise form fields
19
+ }),
20
+ )
21
+
22
+ watch(
23
+ () => props.item,
24
+ (item) => {
25
+ if (item) {
26
+ // TODO: populate form from item
27
+ // Object.assign(form.data, { field: item.field })
28
+ } else {
29
+ form.reset()
30
+ }
31
+ },
32
+ { immediate: true },
33
+ )
34
+
35
+ function handleSubmit() {
36
+ emit('submit', form.data)
37
+ }
38
+ </script>
39
+
40
+ <template>
41
+ <form class="{{ moduleSlug }}-form space-y-4" @submit.prevent="handleSubmit">
42
+ <!-- TODO: add form fields -->
43
+
44
+ <div class="flex justify-end gap-2">
45
+ <button
46
+ type="button"
47
+ class="px-4 py-2 rounded border text-sm"
48
+ :disabled="loading"
49
+ @click="emit('cancel')"
50
+ >
51
+ Cancel
52
+ </button>
53
+ <button
54
+ type="submit"
55
+ class="px-4 py-2 rounded bg-blue-600 text-white text-sm disabled:opacity-50"
56
+ :disabled="loading"
57
+ >
58
+ {{ loading ? 'Saving...' : 'Save' }}
59
+ </button>
60
+ </div>
61
+ </form>
62
+ </template>
@@ -0,0 +1,42 @@
1
+ <script setup lang="ts">
2
+ import type { {{ ModuleName }} } from '../types/{{ moduleSlug }}.types'
3
+
4
+ defineProps<{
5
+ items: {{ ModuleName }}[]
6
+ loading?: boolean
7
+ }>()
8
+
9
+ const emit = defineEmits<{
10
+ edit: [item: {{ ModuleName }}]
11
+ delete: [item: {{ ModuleName }}]
12
+ }>()
13
+ </script>
14
+
15
+ <template>
16
+ <div class="{{ moduleSlug }}-list">
17
+ <div v-if="loading" class="py-8 text-center text-gray-500">Loading...</div>
18
+
19
+ <table v-else class="w-full text-sm">
20
+ <thead>
21
+ <tr class="border-b text-left text-gray-500">
22
+ <th class="pb-2">UUID</th>
23
+ <!-- TODO: add columns -->
24
+ <th class="pb-2 text-right">Actions</th>
25
+ </tr>
26
+ </thead>
27
+ <tbody>
28
+ <tr v-for="item in items" :key="item.uuid" class="border-b hover:bg-gray-50">
29
+ <td class="py-2 font-mono text-xs">{{ item.uuid }}</td>
30
+ <!-- TODO: add cells -->
31
+ <td class="py-2 text-right space-x-2">
32
+ <button class="text-blue-600 hover:underline text-xs" @click="emit('edit', item)">Edit</button>
33
+ <button class="text-red-600 hover:underline text-xs" @click="emit('delete', item)">Delete</button>
34
+ </td>
35
+ </tr>
36
+ <tr v-if="items.length === 0">
37
+ <td colspan="3" class="py-8 text-center text-gray-400">No records found.</td>
38
+ </tr>
39
+ </tbody>
40
+ </table>
41
+ </div>
42
+ </template>
@@ -0,0 +1,4 @@
1
+ export * from './types/{{ moduleSlug }}.types'
2
+ export * from './services/{{ moduleSlug }}.service'
3
+ export * from './stores/{{ moduleSlug }}.store'
4
+ export { default as routes } from './router'
@@ -0,0 +1,27 @@
1
+ <script setup lang="ts">
2
+ import { reactive } from 'vue'
3
+ import { useRouter } from 'vue-router'
4
+ import { Form } from '@devapps/vue-kit'
5
+ import { use{{ ModuleName }}Store } from '../stores/{{ moduleSlug }}.store'
6
+ import {{ ModuleName }}Form from '../components/{{ ModuleName }}Form.vue'
7
+ import type { {{ ModuleName }}Form as {{ ModuleName }}FormData } from '../types/{{ moduleSlug }}.types'
8
+
9
+ const router = useRouter()
10
+ const store = use{{ ModuleName }}Store()
11
+
12
+ async function handleSubmit(data: {{ ModuleName }}FormData) {
13
+ await store.create(data)
14
+ router.push({ name: '{{ moduleSlugPlural }}.index' })
15
+ }
16
+ </script>
17
+
18
+ <template>
19
+ <div class="{{ moduleSlug }}-create-page">
20
+ <h1 class="text-xl font-semibold mb-4">New {{ ModuleName }}</h1>
21
+ <{{ ModuleName }}Form
22
+ :loading="store.saving"
23
+ @submit="handleSubmit"
24
+ @cancel="router.push({ name: '{{ moduleSlugPlural }}.index' })"
25
+ />
26
+ </div>
27
+ </template>
@@ -0,0 +1,34 @@
1
+ <script setup lang="ts">
2
+ import { onMounted } from 'vue'
3
+ import { useRoute, useRouter } from 'vue-router'
4
+ import { use{{ ModuleName }}Store } from '../stores/{{ moduleSlug }}.store'
5
+ import {{ ModuleName }}Form from '../components/{{ ModuleName }}Form.vue'
6
+ import type { {{ ModuleName }}Form as {{ ModuleName }}FormData } from '../types/{{ moduleSlug }}.types'
7
+
8
+ const route = useRoute()
9
+ const router = useRouter()
10
+ const store = use{{ ModuleName }}Store()
11
+
12
+ const uuid = route.params['uuid'] as string
13
+
14
+ onMounted(() => store.fetchOne(uuid))
15
+
16
+ async function handleSubmit(data: {{ ModuleName }}FormData) {
17
+ await store.update(uuid, data)
18
+ router.push({ name: '{{ moduleSlugPlural }}.index' })
19
+ }
20
+ </script>
21
+
22
+ <template>
23
+ <div class="{{ moduleSlug }}-edit-page">
24
+ <h1 class="text-xl font-semibold mb-4">Edit {{ ModuleName }}</h1>
25
+ <div v-if="store.loading">Loading...</div>
26
+ <{{ ModuleName }}Form
27
+ v-else
28
+ :item="store.item"
29
+ :loading="store.saving"
30
+ @submit="handleSubmit"
31
+ @cancel="router.push({ name: '{{ moduleSlugPlural }}.index' })"
32
+ />
33
+ </div>
34
+ </template>
@@ -0,0 +1,59 @@
1
+ <script setup lang="ts">
2
+ import { ref, onMounted } from 'vue'
3
+ import { useRouter } from 'vue-router'
4
+ import { use{{ ModuleName }}Store } from '../stores/{{ moduleSlug }}.store'
5
+ import {{ ModuleName }}List from '../components/{{ ModuleName }}List.vue'
6
+ import {{ ModuleName }}DeleteModal from '../components/{{ ModuleName }}DeleteModal.vue'
7
+ import type { {{ ModuleName }} } from '../types/{{ moduleSlug }}.types'
8
+
9
+ const router = useRouter()
10
+ const store = use{{ ModuleName }}Store()
11
+
12
+ const isDeleteModalOpen = ref(false)
13
+ const {{ moduleName }}ToDelete = ref<{{ ModuleName }} | null>(null)
14
+
15
+ onMounted(() => store.fetchAll())
16
+
17
+ function handleEdit(item: {{ ModuleName }}) {
18
+ router.push({ name: '{{ moduleSlugPlural }}.edit', params: { uuid: item.uuid } })
19
+ }
20
+
21
+ function handleDelete(item: {{ ModuleName }}) {
22
+ {{ moduleName }}ToDelete.value = item
23
+ isDeleteModalOpen.value = true
24
+ }
25
+
26
+ function handleDeleted() {
27
+ isDeleteModalOpen.value = false
28
+ {{ moduleName }}ToDelete.value = null
29
+ store.fetchAll()
30
+ }
31
+ </script>
32
+
33
+ <template>
34
+ <div class="{{ moduleSlug }}-list-page">
35
+ <div class="flex items-center justify-between mb-4">
36
+ <h1 class="text-xl font-semibold">{{ ModuleNamePlural }}</h1>
37
+ <button
38
+ class="px-4 py-2 bg-blue-600 text-white rounded text-sm"
39
+ @click="router.push({ name: '{{ moduleSlugPlural }}.create' })"
40
+ >
41
+ New {{ ModuleName }}
42
+ </button>
43
+ </div>
44
+
45
+ <{{ ModuleName }}List
46
+ :items="store.items"
47
+ :loading="store.loading"
48
+ @edit="handleEdit"
49
+ @delete="handleDelete"
50
+ />
51
+
52
+ <{{ ModuleName }}DeleteModal
53
+ :open="isDeleteModalOpen"
54
+ :item="{{ moduleName }}ToDelete"
55
+ @close="isDeleteModalOpen = false"
56
+ @deleted="handleDeleted"
57
+ />
58
+ </div>
59
+ </template>
@@ -0,0 +1,28 @@
1
+ <script setup lang="ts">
2
+ import { onMounted } from 'vue'
3
+ import { useRoute } from 'vue-router'
4
+ import { use{{ ModuleName }}Store } from '../stores/{{ moduleSlug }}.store'
5
+
6
+ const route = useRoute()
7
+ const store = use{{ ModuleName }}Store()
8
+
9
+ const uuid = route.params['uuid'] as string
10
+
11
+ onMounted(() => store.fetchOne(uuid))
12
+ </script>
13
+
14
+ <template>
15
+ <div class="{{ moduleSlug }}-show-page">
16
+ <h1 class="text-xl font-semibold mb-4">{{ ModuleName }} Details</h1>
17
+
18
+ <div v-if="store.loading" class="py-8 text-gray-500">Loading...</div>
19
+
20
+ <div v-else-if="store.item" class="bg-white p-6 rounded shadow space-y-4">
21
+ <div>
22
+ <span class="text-sm text-gray-500">UUID</span>
23
+ <p class="font-mono">{{ store.item.uuid }}</p>
24
+ </div>
25
+ <!-- TODO: show fields -->
26
+ </div>
27
+ </div>
28
+ </template>
@@ -0,0 +1,26 @@
1
+ import type { RouteRecordRaw } from 'vue-router'
2
+
3
+ const routes: RouteRecordRaw[] = [
4
+ {
5
+ path: '/{{ moduleSlugPlural }}',
6
+ name: '{{ moduleSlugPlural }}.index',
7
+ component: () => import('./pages/{{ ModuleName }}ListPage.vue'),
8
+ },
9
+ {
10
+ path: '/{{ moduleSlugPlural }}/create',
11
+ name: '{{ moduleSlugPlural }}.create',
12
+ component: () => import('./pages/{{ ModuleName }}CreatePage.vue'),
13
+ },
14
+ {
15
+ path: '/{{ moduleSlugPlural }}/:uuid/edit',
16
+ name: '{{ moduleSlugPlural }}.edit',
17
+ component: () => import('./pages/{{ ModuleName }}EditPage.vue'),
18
+ },
19
+ {
20
+ path: '/{{ moduleSlugPlural }}/:uuid',
21
+ name: '{{ moduleSlugPlural }}.show',
22
+ component: () => import('./pages/{{ ModuleName }}ShowPage.vue'),
23
+ },
24
+ ]
25
+
26
+ export default routes
@@ -0,0 +1,9 @@
1
+ import { CrudService } from '@devapps/vue-kit'
2
+ import type { HttpClient } from '@devapps/vue-kit'
3
+ import type { {{ ModuleName }} } from '../types/{{ moduleSlug }}.types'
4
+
5
+ export class {{ ModuleName }}Service extends CrudService<{{ ModuleName }}> {
6
+ constructor(http: HttpClient) {
7
+ super(http, '{{ resourcePath }}')
8
+ }
9
+ }
@@ -0,0 +1,9 @@
1
+ import { defineCrudStore } from '@devapps/vue-kit'
2
+ import { {{ ModuleName }}Service } from '../services/{{ moduleSlug }}.service'
3
+ import type { {{ ModuleName }} } from '../types/{{ moduleSlug }}.types'
4
+ import { useHttpClient } from '@/composables/useHttpClient' // adjust to your project
5
+
6
+ export const use{{ ModuleName }}Store = defineCrudStore<{{ ModuleName }}>(
7
+ '{{ moduleName }}',
8
+ () => new {{ ModuleName }}Service(useHttpClient()),
9
+ )