PluginProbe
The Innovative Form Builder – IvyForms / 0.6
The Innovative Form Builder – IvyForms v0.6
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.6, at frontend/src/stores/useTemplateStore.ts

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