PluginProbe
The Innovative Form Builder – IvyForms / 0.3
The Innovative Form Builder – IvyForms v0.3
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
ivyforms / frontend / src / stores / useTemplateStore.ts

useTemplateStore.ts in The Innovative Form Builder – IvyForms 0.3, at frontend/src/stores/useTemplateStore.ts

188 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { defineStore } from 'pinia'
2 import { ref } from 'vue'
3 import { useLabels } from '@/composables/useLabels'
4 import IvyMessage from '@/views/_components/message/ivyMessage.ts'
5 import { useApiClient } from '@/composables/useApiClient.ts'
6
7 interface FieldData {
8 id: string
9 type: string
10 label: string
11 placeholder?: string
12 required: boolean
13 validation?: Record<string, unknown>
14 settings?: Record<string, unknown>
15 }
16
17 interface FormSettings {
18 success_message?: string
19 [key: string]: unknown
20 }
21
22 interface FormData {
23 name: string
24 description: string
25 status: string
26 published?: boolean
27 showTitle?: boolean
28 showDescription?: boolean
29 storeEntries?: boolean
30 fields: FieldData[]
31 settings: FormSettings
32 }
33
34 interface Template {
35 id: string
36 name: string
37 description: string
38 category: string
39 is_pro: boolean
40 screenshot: string
41 form_data: FormData
42 }
43
44 interface TemplateCategory {
45 name: string
46 description: string
47 }
48
49 export const useTemplateStore = defineStore('ivyformsTemplate', () => {
50 // State
51 const templates = ref<Template[]>([])
52 const categories = ref<Record<string, TemplateCategory>>({})
53 const isLoading = ref(false)
54 const error = ref<string | null>(null)
55
56 // Composables
57 const { getLabel } = useLabels()
58 const { request } = useApiClient()
59
60 // Actions
61 const fetchTemplates = async (): Promise<void> => {
62 isLoading.value = true
63 error.value = null
64
65 try {
66 const { data, error: apiError } = await request('templates', {
67 method: 'GET',
68 })
69
70 if (apiError) {
71 throw new Error(apiError)
72 }
73
74 if (data.data.success) {
75 // Use the associative array from backend, preserve IDs
76 templates.value = Object.values(data.data.data.templates)
77 categories.value = data.data.data.categories
78 } else {
79 throw new Error(getLabel('failed_to_fetch_template'))
80 }
81 } catch (err) {
82 error.value = err instanceof Error ? err.message : getLabel('failed_to_fetch_template')
83 console.error(getLabel('template_fetch_error'), err)
84 IvyMessage({
85 message: `${getLabel('failed_to_fetch_template')} ${error.value}`,
86 type: 'error',
87 })
88 throw err
89 } finally {
90 isLoading.value = false
91 }
92 }
93
94 const getTemplate = async (templateId: string): Promise<Template | null> => {
95 try {
96 const { data, error: apiError } = await request(`template/${templateId}`, {
97 method: 'GET',
98 })
99
100 if (apiError) {
101 throw new Error(apiError)
102 }
103
104 if (data.data.success) {
105 return data.data.data
106 } else {
107 throw new Error(getLabel('failed_to_fetch_template'))
108 }
109 } catch (err) {
110 error.value = err instanceof Error ? err.message : getLabel('failed_to_fetch_template')
111 console.error(getLabel('template_fetch_error'), err)
112 IvyMessage({
113 message: `${getLabel('failed_to_fetch_template')} ${error.value}`,
114 type: 'error',
115 })
116 return null
117 }
118 }
119
120 const getTemplatesByCategory = (categoryId: string): Template[] => {
121 return templates.value.filter((template) => template.category === categoryId)
122 }
123
124 const searchTemplates = (query: string): Template[] => {
125 if (!query.trim()) {
126 return templates.value
127 }
128
129 const searchTerm = query.toLowerCase()
130 return templates.value.filter(
131 (template) =>
132 template.name.toLowerCase().includes(searchTerm) ||
133 template.description.toLowerCase().includes(searchTerm),
134 )
135 }
136
137 const clearError = (): void => {
138 error.value = null
139 }
140
141 const resetStore = (): void => {
142 templates.value = []
143 categories.value = {}
144 isLoading.value = false
145 error.value = null
146 }
147
148 // Getters
149 const getTemplateById = (id: string): Template | undefined => {
150 return templates.value.find((template) => template.id === id)
151 }
152
153 const getAvailableCategories = (): TemplateCategory[] => {
154 return Object.values(categories.value)
155 }
156
157 const getTemplatesCount = (): number => {
158 return templates.value.length
159 }
160
161 const getProTemplatesCount = (): number => {
162 return templates.value.filter((template) => template.is_pro).length
163 }
164
165 const getFreeTemplatesCount = (): number => {
166 return templates.value.filter((template) => !template.is_pro).length
167 }
168
169 return {
170 // State
171 templates,
172 categories,
173 isLoading,
174 error,
175 fetchTemplates,
176 getTemplate,
177 getTemplatesByCategory,
178 searchTemplates,
179 clearError,
180 resetStore,
181 getTemplateById,
182 getAvailableCategories,
183 getTemplatesCount,
184 getProTemplatesCount,
185 getFreeTemplatesCount,
186 }
187 })
188