Finishing the templates pages

This commit is contained in:
Julien Nahum 2023-12-19 15:24:54 +01:00
parent bb519907f6
commit 8e70d6be98
10 changed files with 295 additions and 352 deletions

View File

@ -1,51 +1,48 @@
<template>
<div v-if="template">
<!-- <template v-if="displayAll">-->
<!-- <span v-if="template.is_new"-->
<!-- class="inline-flex items-center gap-1 px-2 py-1 text-xs font-medium text-white bg-blue-500 rounded-full"-->
<!-- >-->
<!-- <svg aria-hidden="true" class="w-3 h-3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"-->
<!-- fill="currentColor"-->
<!-- >-->
<!-- <path fill-rule="evenodd"-->
<!-- d="M5 2a1 1 0 011 1v1h1a1 1 0 010 2H6v1a1 1 0 01-2 0V6H3a1 1 0 010-2h1V3a1 1 0 011-1zm0 10a1 1 0 011 1v1h1a1 1 0 110 2H6v1a1 1 0 11-2 0v-1H3a1 1 0 110-2h1v-1a1 1 0 011-1zM12 2a1 1 0 01.967.744L14.146 7.2 17.5 9.134a1 1 0 010 1.732l-3.354 1.935-1.18 4.455a1 1 0 01-1.933 0L9.854 12.8 6.5 10.866a1 1 0 010-1.732l3.354-1.935 1.18-4.455A1 1 0 0112 2z"-->
<!-- clip-rule="evenodd"-->
<!-- />-->
<!-- </svg>-->
<!-- New-->
<!-- </span>-->
<!-- <span v-for="item in types"-->
<!-- class="inline-flex items-center rounded-full bg-gray-50 dark:bg-gray-800 dark:text-gray-400 px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10"-->
<!-- >-->
<!-- {{ item }}-->
<!-- </span>-->
<!-- <span v-for="item in industries"-->
<!-- class="inline-flex items-center rounded-full bg-blue-50 dark:bg-blue-900 dark:text-gray-400 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-700/10"-->
<!-- >-->
<!-- {{ item }}-->
<!-- </span>-->
<!-- </template>-->
<!-- <template v-else>-->
<!-- <span v-if="types.length > 0"-->
<!-- class="inline-flex items-center rounded-full bg-gray-50 px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10"-->
<!-- >-->
<!-- {{ types[0] }} <template v-if="types.length > 1">+{{ types.length - 1 }}</template>-->
<!-- </span>-->
<!-- <span v-if="industries.length > 0"-->
<!-- class="inline-flex items-center rounded-full bg-blue-50 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-700/10"-->
<!-- >-->
<!-- {{ industries[0] }} <template v-if="industries.length > 1">+{{ industries.length - 1 }}</template>-->
<!-- </span>-->
<!-- </template>-->
<div>
<template v-if="displayAll">
<span v-if="template.is_new"
class="inline-flex items-center gap-1 px-2 py-1 text-xs font-medium text-white bg-blue-500 rounded-full"
>
<svg aria-hidden="true" class="w-3 h-3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"
fill="currentColor"
>
<path fill-rule="evenodd"
d="M5 2a1 1 0 011 1v1h1a1 1 0 010 2H6v1a1 1 0 01-2 0V6H3a1 1 0 010-2h1V3a1 1 0 011-1zm0 10a1 1 0 011 1v1h1a1 1 0 110 2H6v1a1 1 0 11-2 0v-1H3a1 1 0 110-2h1v-1a1 1 0 011-1zM12 2a1 1 0 01.967.744L14.146 7.2 17.5 9.134a1 1 0 010 1.732l-3.354 1.935-1.18 4.455a1 1 0 01-1.933 0L9.854 12.8 6.5 10.866a1 1 0 010-1.732l3.354-1.935 1.18-4.455A1 1 0 0112 2z"
clip-rule="evenodd"
/>
</svg>
New
</span>
<span v-for="item in types" :key="item.slug"
class="inline-flex items-center rounded-full bg-gray-50 dark:bg-gray-800 dark:text-gray-400 px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10"
>
{{ item.name }}
</span>
<span v-for="item in industries" :key="item.slug"
class="inline-flex items-center rounded-full bg-blue-50 dark:bg-blue-900 dark:text-gray-400 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-700/10"
>
{{ item.name }}
</span>
</template>
<template v-else>
<span v-if="types.length > 0"
class="inline-flex items-center rounded-full bg-gray-50 px-2 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10"
>
{{ types[0].name }} <template v-if="types.length > 1">+{{ types.length - 1 }}</template>
</span>
<span v-if="industries.length > 0"
class="inline-flex items-center rounded-full bg-blue-50 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-700/10"
>
{{ industries[0].name }} <template v-if="industries.length > 1">+{{ industries.length - 1 }}</template>
</span>
</template>
</div>
</template>
<script>
import { computed } from 'vue'
import { useTemplatesStore } from '../../../stores/templates'
<script setup>
export default {
props: {
const props = defineProps({
template: {
type: Object,
required: true
@ -54,31 +51,9 @@ export default {
type: Boolean,
default: false
}
},
})
setup () {
const templatesStore = useTemplatesStore()
return {
templatesStore
}
},
data: () => ({}),
computed: {
// template () {
// return this.templatesStore.getByKey(this.slug)
// },
// types () {
// if (!this.template) return null
// return this.templatesStore.getTemplateTypes(this.template.types)
// },
// industries () {
// if (!this.template) return null
// return this.templatesStore.getTemplateIndustries(this.template.industries)
// }
},
methods: {}
}
const types = computed(() => templatesStore.getTemplateTypes(props.template.types))
const industries = computed(() => templatesStore.getTemplateIndustries(props.template.industries))
</script>

View File

@ -16,7 +16,7 @@
</div>
</div>
<div class="flex-1 w-full md:max-w-xs">
<text-input autocomplete="off" name="search" :form="searchTemplate" placeholder="Search..."/>
<text-input autocomplete="off" name="search" v-model="search" placeholder="Search..."/>
</div>
</div>
@ -45,7 +45,7 @@
<div class="grid grid-cols-1 gap-8 mt-8 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
<router-link v-for="row in types" :key="row.slug"
:to="{params:{slug:row.slug}, name:'templates-types'}"
:to="{params: {slug:row.slug}, name:'templates-types-slug'}"
:title="row.name"
class="text-gray-600 dark:text-gray-400 transition-colors duration-300 hover:text-nt-blue"
>
@ -65,7 +65,7 @@
<div class="grid grid-cols-1 gap-8 mt-8 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
<router-link v-for="row in industries" :key="row.slug"
:to="{params:{slug:row.slug}, name:'templates-industries'}"
:to="{params:{slug:row.slug}, name:'templates-industries-slug'}"
:title="row.name"
class="text-gray-600 dark:text-gray-400 transition-colors duration-300 hover:text-nt-blue"
>
@ -79,9 +79,9 @@
<script>
import {computed} from 'vue'
import Form from 'vform'
import Fuse from 'fuse.js'
import SingleTemplate from './SingleTemplate.vue'
import {refThrottled} from "@vueuse/core";
export default {
name: 'TemplatesList',
@ -100,23 +100,22 @@ export default {
setup() {
const authStore = useAuthStore()
const templatesStore = useTemplatesStore()
const search = ref('')
const throttledSearch = refThrottled(search, 1000)
return {
search,
throttledSearch,
user: computed(() => authStore.user),
industries: computed(() => templatesStore.industries),
types: computed(() => templatesStore.types)
industries: computed(() => [...templatesStore.industries.values()]),
types: computed(() => [...templatesStore.types.values()])
}
},
data: () => ({
selectedType: 'all',
selectedIndustry: 'all',
searchTemplate: new Form({
search: ''
})
}),
watch: {},
computed: {
industriesOptions() {
return [{name: 'All Industries', value: 'all'}].concat(Object.values(this.industries).map((industry) => {
@ -151,7 +150,8 @@ export default {
})
}
if (this.searchTemplate.search === '' || this.searchTemplate.search === null) {
console.log(this.throttledSearch, '---inode')
if (!this.throttledSearch || this.throttledSearch === '' || this.throttledSearch === null) {
return enrichedTemplates
}
@ -165,7 +165,7 @@ export default {
]
}
const fuse = new Fuse(enrichedTemplates, fuzeOptions)
return fuse.search(this.searchTemplate.search).map((res) => {
return fuse.search(this.throttledSearch).map((res) => {
return res.item
})
}

View File

@ -45,9 +45,9 @@
<p class="mt-2 text-lg font-normal text-gray-600">
{{ cleanQuotes(template.short_description) }}
</p>
<!-- <template-tags :slug="template.slug" :display-all="true"-->
<!-- class="flex flex-wrap items-center justify-center gap-3 mt-4 md:justify-start"-->
<!-- />-->
<template-tags :template="template" :display-all="true"
class="flex flex-wrap items-center justify-center gap-3 mt-4 md:justify-start"
/>
</div>
</div>
</div>
@ -226,6 +226,7 @@ const {data: relatedTemplatesData} = await useAsyncData('related-templates', ()
}))
})
templatesStore.save(relatedTemplatesData.value)
templatesStore.initTypesAndIndustries()
// State
const showFormTemplateModal = ref(false)
@ -235,7 +236,7 @@ const breadcrumbs = computed(() => {
if (!template.value) {
return [{route: {name: 'templates'}, label: 'Templates'}]
}
return [{route: {name: 'templates'}, label: 'Templates'}, {label: template.name}]
return [{route: {name: 'templates'}, label: 'Templates'}, {label: template.value.name}]
})
const relatedTemplates = computed(() => templatesStore.getByKey(template?.value?.related_templates))
const canEditTemplate = computed(() => authStore.authenticated && template.value && (authStore.user.admin || authStore.user.template_editor || template.creator_id === authStore.user.id))

View File

@ -31,6 +31,7 @@ const templatesStore = useTemplatesStore()
if (!templatesStore.allLoaded) {
templatesStore.startLoading()
templatesStore.initTypesAndIndustries()
const {data} = await fetchAllTemplates()
templatesStore.set(data.value)
templatesStore.allLoaded = true

View File

@ -76,7 +76,7 @@
<div class="grid grid-cols-1 gap-8 mt-8 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
<router-link v-for="row in otherIndustries" :key="row.slug"
:to="{params:{slug:row.slug}, name:'templates-industries'}"
:to="{params:{slug:row.slug}, name:'templates-industries-slug'}"
:title="row.name"
class="text-gray-600 dark:text-gray-400 transition-colors duration-300 hover:text-nt-blue"
>
@ -96,12 +96,12 @@
import Form from 'vform'
import Fuse from 'fuse.js'
import { computed } from 'vue'
import { useAuthStore } from '../../stores/auth'
import { useTemplatesStore } from '../../stores/templates'
import SeoMeta from '../../mixins/seo-meta.js'
import OpenFormFooter from '../../components/pages/OpenFormFooter.vue'
import { useAuthStore } from '../../../stores/auth.js'
import { useTemplatesStore } from '../../../stores/templates.js'
import SeoMeta from '../../../mixins/seo-meta.js'
import OpenFormFooter from '../../../components/pages/OpenFormFooter.vue'
import Breadcrumb from '~/components/global/Breadcrumb.vue'
import SingleTemplate from '../../components/pages/templates/SingleTemplate.vue'
import SingleTemplate from '../../../components/pages/templates/SingleTemplate.vue'
const loadTemplates = function () {
const templatesStore = useTemplatesStore()

View File

@ -1,238 +0,0 @@
<template>
<div class="flex flex-col min-h-full">
<breadcrumb :path="breadcrumbs" />
<div v-if="templatesLoading" class="text-center my-4">
<Loader class="h-6 w-6 text-nt-blue mx-auto" />
</div>
<p v-else-if="type === null || !type" class="text-center my-4">
We could not find this type.
</p>
<template v-else>
<section class="py-12 sm:py-16 bg-gray-50 border-b border-gray-200">
<div class="px-4 sm:px-6 lg:px-8 max-w-7xl mx-auto">
<div class="text-center mx-auto">
<div class="font-semibold sm:w-full text-blue-500 mb-3">
{{ type.name }}
</div>
<h1 class="text-3xl sm:text-4xl lg:text-5xl font-bold tracking-tight text-gray-900">
{{ type.meta_title }}
</h1>
<p class="max-w-xl mx-auto text-gray-600 mt-4 text-lg font-normal">
{{ type.meta_description }}
</p>
</div>
</div>
</section>
<section class="bg-white py-12 sm:py-16">
<div class="px-4 sm:px-6 lg:px-8 max-w-7xl mx-auto">
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 sm:gap-6 relative z-20">
<div class="flex items-center gap-4">
<div class="flex-1 sm:flex-none">
<select-input v-model="selectedIndustry" name="industry"
:options="industriesOptions" class="w-full sm:w-auto md:w-56"
/>
</div>
</div>
<div class="flex-1 w-full md:max-w-xs">
<text-input name="search" :form="searchTemplate" placeholder="Search..." />
</div>
</div>
<div v-if="templatesLoading" class="text-center mt-4">
<Loader class="h-6 w-6 text-nt-blue mx-auto" />
</div>
<p v-else-if="enrichedTemplates.length === 0" class="text-center mt-4">
No templates found.
</p>
<div v-else class="relative z-10">
<div class="grid grid-cols-1 mt-8 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-8 sm:gap-y-12">
<single-template v-for="template in enrichedTemplates" :key="template.id" :slug="template.slug" />
</div>
</div>
</div>
</section>
<section class="py-12 bg-white border-t border-gray-200 sm:py-16">
<div class="px-4 mx-auto sm:px-6 lg:px-8 max-w-7xl">
<p class="text-gray-600 font-normal">
{{ type.description }}
</p>
</div>
</section>
<section class="py-12 bg-white border-t border-gray-200 sm:py-16">
<div class="px-4 mx-auto sm:px-6 lg:px-8 max-w-7xl">
<div class="flex items-center justify-between">
<h4 class="text-xl font-bold tracking-tight text-gray-900 sm:text-2xl">
Other Types
</h4>
<v-button :to="{name:'templates'}" color="white" size="small" :arrow="true">
View All Templates
</v-button>
</div>
<div class="grid grid-cols-1 gap-8 mt-8 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
<router-link v-for="row in otherTypes" :key="row.slug"
:to="{params:{slug:row.slug}, name:'templates-types'}"
:title="row.name"
class="text-gray-600 dark:text-gray-400 transition-colors duration-300 hover:text-nt-blue"
>
{{ row.name }}
</router-link>
</div>
</div>
</section>
</template>
<open-form-footer class="mt-8 border-t"/>
</div>
</template>
<script>
import Form from 'vform'
import Fuse from 'fuse.js'
import { computed } from 'vue'
import { useAuthStore } from '../../stores/auth'
import { useTemplatesStore } from '../../stores/templates'
import SeoMeta from '../../mixins/seo-meta.js'
import OpenFormFooter from '../../components/pages/OpenFormFooter.vue'
import Breadcrumb from '~/components/global/Breadcrumb.vue'
import SingleTemplate from '../../components/pages/templates/SingleTemplate.vue'
const loadTemplates = function () {
const templatesStore = useTemplatesStore()
templatesStore.startLoading()
templatesStore.loadIfEmpty().then(() => {
templatesStore.stopLoading()
})
}
export default {
components: { Breadcrumb, OpenFormFooter, SingleTemplate },
mixins: [SeoMeta],
beforeRouteEnter (to, from, next) {
loadTemplates()
next()
},
setup () {
const authStore = useAuthStore()
const templatesStore = useTemplatesStore()
return {
authenticated : computed(() => authStore.check),
user : computed(() => authStore.user),
templates : computed(() => templatesStore.content),
templatesLoading : computed(() => templatesStore.loading),
industries : computed(() => templatesStore.industries),
types : computed(() => templatesStore.types)
}
},
data () {
return {
selectedIndustry: 'all',
searchTemplate: new Form({
search: ''
})
}
},
mounted () {},
computed: {
breadcrumbs () {
if (!this.type) {
return [{ route: { name: 'templates' }, label: 'Templates' }]
}
return [{ route: { name: 'templates' }, label: 'Templates' }, { label: this.type.name }]
},
type () {
return Object.values(this.types).find((type) => {
return type.slug === this.$route.params.slug
})
},
industriesOptions () {
return [{ name: 'All Industries', value: 'all' }].concat(Object.values(this.industries).map((industry) => {
return {
name: industry.name,
value: industry.slug
}
}))
},
otherTypes() {
return Object.values(this.types).filter((type) => {
return type.slug !== this.$route.params.slug
})
},
enrichedTemplates () {
let enrichedTemplates = this.templates
// Filter by current Type only
enrichedTemplates = enrichedTemplates.filter((item) => {
return (item.types && item.types.length > 0) ? item.types.includes(this.$route.params.slug) : false
})
// Filter by Selected Industry
if (this.selectedIndustry && this.selectedIndustry !== 'all') {
enrichedTemplates = enrichedTemplates.filter((item) => {
return (item.industries && item.industries.length > 0) ? item.industries.includes(this.selectedIndustry) : false
})
}
if (this.searchTemplate.search === '' || this.searchTemplate.search === null) {
return enrichedTemplates
}
// Fuze search
const fuzeOptions = {
keys: [
'name',
'slug',
'description',
'short_description'
]
}
const fuse = new Fuse(enrichedTemplates, fuzeOptions)
return fuse.search(this.searchTemplate.search).map((res) => {
return res.item
})
},
metaTitle () {
return this.type ? this.type.meta_title : 'Form Template Type'
},
metaDescription () {
if (!this.type) return null
return this.type.meta_description.substring(0, 140)
}
},
methods: {}
}
</script>
<style lang='scss'>
.nf-text {
@apply space-y-4;
h2 {
@apply text-sm font-normal tracking-widest text-gray-500 uppercase;
}
p {
@apply font-normal leading-7 text-gray-900 dark:text-gray-100;
}
ol {
@apply list-decimal list-inside;
}
ul {
@apply list-disc list-inside;
}
}
</style>

View File

@ -0,0 +1,200 @@
<template>
<div class="flex flex-col min-h-full">
<breadcrumb :path="breadcrumbs"/>
<div v-if="templatesLoading" class="text-center my-4">
<Loader class="h-6 w-6 text-nt-blue mx-auto"/>
</div>
<p v-else-if="type === null || !type" class="text-center my-4">
We could not find this type.
</p>
<template v-else>
<section class="py-12 sm:py-16 bg-gray-50 border-b border-gray-200">
<div class="px-4 sm:px-6 lg:px-8 max-w-7xl mx-auto">
<div class="text-center mx-auto">
<div class="font-semibold sm:w-full text-blue-500 mb-3">
{{ type.name }}
</div>
<h1 class="text-3xl sm:text-4xl lg:text-5xl font-bold tracking-tight text-gray-900">
{{ type.meta_title }}
</h1>
<p class="max-w-xl mx-auto text-gray-600 mt-4 text-lg font-normal">
{{ type.meta_description }}
</p>
</div>
</div>
</section>
<section class="bg-white py-12 sm:py-16">
<div class="px-4 sm:px-6 lg:px-8 max-w-7xl mx-auto">
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 sm:gap-6 relative z-20">
<div class="flex items-center gap-4">
<div class="flex-1 sm:flex-none">
<select-input v-model="selectedIndustry" name="industry"
:options="industriesOptions" class="w-full sm:w-auto md:w-56"
/>
</div>
</div>
<div class="flex-1 w-full md:max-w-xs">
<text-input name="search" :form="searchTemplate" placeholder="Search..."/>
</div>
</div>
<div v-if="templatesLoading" class="text-center mt-4">
<Loader class="h-6 w-6 text-nt-blue mx-auto"/>
</div>
<p v-else-if="enrichedTemplates.length === 0" class="text-center mt-4">
No templates found.
</p>
<div v-else class="relative z-10">
<div class="grid grid-cols-1 mt-8 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-8 sm:gap-y-12">
<single-template v-for="template in enrichedTemplates" :key="template.id" :slug="template.slug"/>
</div>
</div>
</div>
</section>
<section class="py-12 bg-white border-t border-gray-200 sm:py-16">
<div class="px-4 mx-auto sm:px-6 lg:px-8 max-w-7xl">
<p class="text-gray-600 font-normal">
{{ type.description }}
</p>
</div>
</section>
<section class="py-12 bg-white border-t border-gray-200 sm:py-16">
<div class="px-4 mx-auto sm:px-6 lg:px-8 max-w-7xl">
<div class="flex items-center justify-between">
<h4 class="text-xl font-bold tracking-tight text-gray-900 sm:text-2xl">
Other Types
</h4>
<v-button :to="{name:'templates'}" color="white" size="small" :arrow="true">
View All Templates
</v-button>
</div>
<div class="grid grid-cols-1 gap-8 mt-8 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
<router-link v-for="row in otherTypes" :key="row.slug"
:to="{params:{slug:row.slug}, name:'templates-types-slug'}"
:title="row.name"
class="text-gray-600 dark:text-gray-400 transition-colors duration-300 hover:text-nt-blue"
>
{{ row.name }}
</router-link>
</div>
</div>
</section>
</template>
<open-form-footer class="mt-8 border-t"/>
</div>
</template>
<script>
import {computed} from 'vue'
import SeoMeta from '../../../mixins/seo-meta.js'
import OpenFormFooter from '../../../components/pages/OpenFormFooter.vue'
import Breadcrumb from '~/components/global/Breadcrumb.vue'
import SingleTemplate from '../../../components/pages/templates/SingleTemplate.vue'
const authStore = useAuthStore()
const templatesStore = useTemplatesStore()
const route = useRoute()
// State
const selectedIndustry = ref('all')
const searchTemplate = useForm({
search: ''
})
// Computed
const authenticated = computed(() => authStore.check)
const user = computed(() => authStore.user)
const templates = computed(() => templatesStore.getAll)
const breadcrumbs = computed(() => {
if (!type) {
return [{route: {name: 'templates'}, label: 'Templates'}]
}
return [{route: {name: 'templates'}, label: 'Templates'}, {label: type.name}]
})
const type = computed(() => templatesStore.types.value.get(route.params.slug))
const types = computed(() => [...templatesStore.types.value.values()])
const industriesOptions = computed(() => [{name: 'All Industries', value: 'all'}].concat(
[...templatesStore.types.values.values()].map((industry) => {
return {
name: industry.name,
value: industry.slug
}
})))
// enrichedTemplates()
// {
// let enrichedTemplates = this.templates
//
// // Filter by current Type only
// enrichedTemplates = enrichedTemplates.filter((item) => {
// return (item.types && item.types.length > 0) ? item.types.includes(this.$route.params.slug) : false
// })
//
// // Filter by Selected Industry
// if (this.selectedIndustry && this.selectedIndustry !== 'all') {
// enrichedTemplates = enrichedTemplates.filter((item) => {
// return (item.industries && item.industries.length > 0) ? item.industries.includes(this.selectedIndustry) : false
// })
// }
//
// if (this.searchTemplate.search === '' || this.searchTemplate.search === null) {
// return enrichedTemplates
// }
//
// // Fuze search
// const fuzeOptions = {
// keys: [
// 'name',
// 'slug',
// 'description',
// 'short_description'
// ]
// }
// const fuse = new Fuse(enrichedTemplates, fuzeOptions)
// return fuse.search(this.searchTemplate.search).map((res) => {
// return res.item
// })
// }
// ,
// metaTitle()
// {
// return this.type ? this.type.meta_title : 'Form Template Type'
// }
// ,
// metaDescription()
// {
// if (!this.type) return null
// return this.type.meta_description.substring(0, 140)
// }
</script>
<style lang='scss'>
.nf-text {
@apply space-y-4;
h2 {
@apply text-sm font-normal tracking-widest text-gray-500 uppercase;
}
p {
@apply font-normal leading-7 text-gray-900 dark:text-gray-100;
}
ol {
@apply list-decimal list-inside;
}
ul {
@apply list-disc list-inside;
}
}
</style>

View File

@ -1,5 +1,7 @@
import {defineStore} from 'pinia'
import {useContentStore} from "~/composables/stores/useContentStore.js";
import templateTypes from "~/data/forms/templates/types.json"
import industryTypes from "~/data/forms/templates/industries.json"
const templatesEndpoint = 'templates'
export const useTemplatesStore = defineStore('templates', () => {
@ -7,29 +9,26 @@ export const useTemplatesStore = defineStore('templates', () => {
const contentStore = useContentStore('slug')
const allLoaded = ref(false)
const industries = ref({})
const types = ref({})
const industries = ref(new Map)
const types = ref(new Map)
const getTemplateTypes = computed((state) => (slugs) => {
if (state.types.length === 0) return null
return Object.values(state.types).filter((val) => slugs.includes(val.slug)).map((item) => {
return item.name
})
// todo: use map
})
const getTemplateIndustries = computed((state) => (slugs) => {
if (state.industries.length === 0) return null
return Object.values(state.industries).filter((val) => slugs.includes(val.slug)).map((item) => {
return item.name
})
})
const getTemplateTypes = (slugs) => {
return slugs.map((slug) => {
return types.value.get(slug)
}).filter((item) => item !== undefined)
}
const getTemplateIndustries =(slugs) => {
return slugs.map((slug) => {
return industries.value.get(slug)
}).filter((item) => item !== undefined)
}
const loadTypesAndIndustries = function() {
if (Object.keys(this.industries).length === 0 || Object.keys(this.types).length === 0) {
// const files = import.meta.glob('~/data/forms/templates/*.json')
// console.log(await files['/data/forms/templates/industries.json']())
// this.industries = await files['/data/forms/templates/industries.json']()
// this.types = await files['/data/forms/templates/types.json']()
const initTypesAndIndustries = () => {
if (types.value.size === 0) {
types.value = new Map(Object.entries(templateTypes))
}
if (industries.value.size === 0) {
industries.value = new Map(Object.entries(industryTypes))
}
}
@ -39,7 +38,7 @@ export const useTemplatesStore = defineStore('templates', () => {
types,
getTemplateTypes,
getTemplateIndustries,
loadTypesAndIndustries,
initTypesAndIndustries
}
})
@ -51,3 +50,8 @@ export const fetchAllTemplates = () => {
return useOpnApi(templatesEndpoint)
}
export const loadTypesAndIndustries = () => {
// Load the json files
}