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

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