@dargmuesli/nuxt-vio 2.0.1 → 3.0.0-beta.10

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 (79) hide show
  1. package/app.config.ts +83 -40
  2. package/components/vio/_/VioApp.vue +92 -0
  3. package/components/{VioError.vue → vio/_/VioError.vue} +1 -1
  4. package/components/{VioLink.vue → vio/_/VioLink.vue} +2 -2
  5. package/components/vio/button/VioButtonColored.vue +52 -0
  6. package/components/vio/card/VioCard.vue +19 -0
  7. package/components/vio/card/state/VioCardState.vue +20 -0
  8. package/components/vio/card/state/VioCardStateAlert.vue +14 -0
  9. package/components/vio/form/VioForm.vue +84 -0
  10. package/components/vio/form/VioFormCheckbox.vue +27 -0
  11. package/components/vio/form/input/VioFormInput.vue +192 -0
  12. package/components/vio/form/input/VioFormInputIconWrapper.vue +7 -0
  13. package/components/vio/form/input/VioFormInputUrl.vue +54 -0
  14. package/components/vio/form/input/state/VioFormInputState.vue +5 -0
  15. package/components/vio/form/input/state/VioFormInputStateError.vue +32 -0
  16. package/components/vio/form/input/state/VioFormInputStateInfo.vue +32 -0
  17. package/components/vio/icon/IconArrowRight.vue +31 -0
  18. package/components/vio/icon/IconCalendar.vue +31 -0
  19. package/components/vio/icon/IconChatOutline.vue +27 -0
  20. package/components/vio/icon/IconChatSolid.vue +26 -0
  21. package/components/vio/icon/IconCheckCircle.vue +29 -0
  22. package/components/vio/icon/IconContainer.vue +15 -0
  23. package/components/vio/icon/IconDownload.vue +31 -0
  24. package/components/vio/icon/IconExclamationCircle.vue +29 -0
  25. package/components/vio/icon/IconHome.vue +31 -0
  26. package/components/vio/icon/IconHourglass.vue +32 -0
  27. package/components/vio/icon/IconLightbulb.vue +27 -0
  28. package/components/vio/icon/IconLogo.vue +17 -0
  29. package/components/vio/icon/IconMixcloud.vue +23 -0
  30. package/components/vio/icon/IconMusic.vue +27 -0
  31. package/components/vio/icon/IconPlay.vue +25 -0
  32. package/components/vio/icon/IconShare.vue +27 -0
  33. package/components/{VioLayout.vue → vio/layout/VioLayout.vue} +1 -1
  34. package/components/vio/layout/VioLayoutBreadcrumbs.vue +83 -0
  35. package/components/vio/layout/VioLayoutFooter.vue +40 -0
  36. package/components/vio/layout/VioLayoutFooterCategory.vue +17 -0
  37. package/components/vio/layout/VioLayoutHeader.vue +98 -0
  38. package/components/vio/layout/VioLayoutSpanList.vue +20 -0
  39. package/components/vio/loader/indicator/VioLoaderIndicator.vue +14 -0
  40. package/components/vio/loader/indicator/VioLoaderIndicatorPing.vue +12 -0
  41. package/components/vio/loader/indicator/VioLoaderIndicatorSpinner.vue +24 -0
  42. package/components/{VioLegalNotice.vue → vio/page/VioPageLegalNotice.vue} +10 -8
  43. package/components/{VioPrivacyPolicy.vue → vio/page/VioPagePrivacyPolicy.vue} +19 -12
  44. package/composables/useAppLayout.ts +12 -18
  45. package/composables/useDateTime.ts +17 -0
  46. package/composables/useFavicons.ts +5 -33
  47. package/composables/useFireError.ts +17 -0
  48. package/composables/useGetServiceHref.ts +21 -0
  49. package/composables/useHeadDefault.ts +21 -0
  50. package/composables/usePolyfills.ts +23 -0
  51. package/composables/useStrapiFetch.ts +10 -0
  52. package/error.vue +5 -2
  53. package/locales/de.json +7 -1
  54. package/locales/en.json +7 -1
  55. package/nuxt.config.ts +56 -10
  56. package/package.json +37 -25
  57. package/pages/legal-notice.vue +1 -1
  58. package/pages/privacy-policy.vue +1 -1
  59. package/plugins/dayjs.ts +34 -0
  60. package/plugins/gtag.client.ts +3 -0
  61. package/plugins/i18n.ts +5 -0
  62. package/plugins/marked.ts +9 -0
  63. package/server/middleware/headers.ts +41 -10
  64. package/server/tsconfig.json +1 -1
  65. package/server/utils/util.ts +2 -0
  66. package/store/auth.ts +32 -0
  67. package/tailwind.config.ts +131 -10
  68. package/types/api.d.ts +9 -0
  69. package/types/fetch.d.ts +8 -0
  70. package/types/modules/gql.d.ts +6 -0
  71. package/types/modules/graphql.d.ts +6 -0
  72. package/utils/constants.ts +10 -1
  73. package/utils/form.ts +19 -0
  74. package/utils/networking.ts +117 -0
  75. package/utils/text.ts +20 -0
  76. package/LICENSE +0 -674
  77. package/components/VioApp.vue +0 -59
  78. /package/components/{VioButton.vue → vio/button/VioButton.vue} +0 -0
  79. /package/components/{VioHr.vue → vio/layout/VioLayoutHr.vue} +0 -0
@@ -0,0 +1,40 @@
1
+ <template>
2
+ <footer class="text-sm leading-6">
3
+ <div class="flex flex-col gap-8">
4
+ <div class="flex items-center">
5
+ <VioLayoutHr />
6
+ <IconLogo class="mx-12 h-12 w-12 brightness-0 opacity-60 invert" />
7
+ <VioLayoutHr />
8
+ </div>
9
+ <!-- Justifying evenly, instead of "between", centers a single element. -->
10
+ <div class="flex flex-wrap justify-evenly">
11
+ <slot />
12
+ </div>
13
+ <p class="text-center text-gray-500 dark:text-gray-400">
14
+ {{
15
+ t('copyright', {
16
+ name: 'Jonas Thelemann',
17
+ year,
18
+ })
19
+ }}
20
+ </p>
21
+ </div>
22
+ </footer>
23
+ </template>
24
+
25
+ <script setup lang="ts">
26
+ const { t } = useI18n()
27
+ const config = useRuntimeConfig()
28
+
29
+ // computations
30
+ const year = computed(() =>
31
+ config.public.isTesting ? 1337 : new Date().getFullYear(),
32
+ )
33
+ </script>
34
+
35
+ <i18n lang="yaml">
36
+ de:
37
+ copyright: © {year} {name}. Alle Rechte vorbehalten.
38
+ en:
39
+ copyright: © {year} {name}. All rights reserved.
40
+ </i18n>
@@ -0,0 +1,17 @@
1
+ <template>
2
+ <div
3
+ class="flex flex-1 flex-col items-start p-4 basis-1/2 md:flex-none md:basis-auto gap-2"
4
+ >
5
+ <span class="whitespace-nowrap text-lg font-medium leading-7">
6
+ {{ heading }}
7
+ </span>
8
+ <slot />
9
+ </div>
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ export interface Props {
14
+ heading: string
15
+ }
16
+ withDefaults(defineProps<Props>(), {})
17
+ </script>
@@ -0,0 +1,98 @@
1
+ <template>
2
+ <header class="flex items-center justify-between gap-4 mb-8">
3
+ <VioButton :aria-label="t('creal')" :to="localePath('/')">
4
+ <span class="text-lg font-bold">{{ t('creal') }}</span>
5
+ <template #prefix>
6
+ <IconLogo class="h-10 w-10" />
7
+ </template>
8
+ </VioButton>
9
+ <VioLink
10
+ v-if="eventsCurrentCount"
11
+ class="flex items-center gap-2 rounded-full border px-4 py-2 font-bold focus:rounded-full sm:px-4"
12
+ :is-colored="false"
13
+ :to="localePath('/events')"
14
+ >
15
+ <VioLayoutLivePulse />
16
+ <span class="hidden whitespace-nowrap sm:inline">
17
+ {{ t('live') }}
18
+ </span>
19
+ </VioLink>
20
+ <VioLink
21
+ v-else-if="eventsFutureCount"
22
+ class="flex items-center gap-2 rounded-full border px-2 py-2 font-bold focus:rounded-full sm:px-4"
23
+ :is-colored="false"
24
+ :to="localePath('/events')"
25
+ >
26
+ <VioLayoutLivePulse />
27
+ <span class="hidden whitespace-nowrap sm:inline">
28
+ {{ t('eventsFuture') }}
29
+ </span>
30
+ </VioLink>
31
+ <VioButton
32
+ :aria-label="t('bookCreal')"
33
+ class="basis-0 text-lg font-bold"
34
+ :is-colored="false"
35
+ :to="`mailto:e-mail+creal@jonas-thelemann.de?subject=${encodeURIComponent(
36
+ t('bookingSubject'),
37
+ )}`"
38
+ >
39
+ <span class="basis-0 whitespace-nowrap">{{ t('bookCreal') }}</span>
40
+ <template #suffix>
41
+ <IconArrowRight />
42
+ </template>
43
+ </VioButton>
44
+ </header>
45
+ </template>
46
+
47
+ <script setup lang="ts">
48
+ const { $dayjs } = useNuxtApp()
49
+ const { t } = useI18n()
50
+ const localePath = useLocalePath()
51
+ const strapiFetch = useStrapiFetch()
52
+
53
+ // async data
54
+ let eventsCurrentCount = 0
55
+ let eventsFutureCount = 0
56
+
57
+ // methods
58
+ const init = async () => {
59
+ eventsCurrentCount = (
60
+ (await strapiFetch('/events', {
61
+ query: {
62
+ 'filters[$and][0][dateStart][$lte]': $dayjs().toISOString(),
63
+ 'filters[$and][1][$or][0][dateEnd][$gt]': $dayjs().toISOString(),
64
+ 'filters[$and][1][$or][1][dateStart][$gte]': $dayjs()
65
+ .startOf('day')
66
+ .toISOString(),
67
+ },
68
+ })) as any
69
+ ).meta.pagination.total
70
+ eventsFutureCount = (
71
+ (await strapiFetch('/events', {
72
+ query: {
73
+ 'filters[dateStart][$gt]': $dayjs().toISOString(),
74
+ },
75
+ })) as any
76
+ ).meta.pagination.total
77
+ }
78
+
79
+ // initialization
80
+ try {
81
+ await init()
82
+ } catch (error: any) {}
83
+ </script>
84
+
85
+ <i18n lang="yaml">
86
+ en:
87
+ bookCreal: Book cReal
88
+ bookingSubject: Booking Request
89
+ creal: cReal
90
+ eventsFuture: Upcoming events
91
+ live: Live
92
+ de:
93
+ bookCreal: cReal buchen
94
+ bookingSubject: Buchungsanfrage
95
+ creal: cReal
96
+ eventsFuture: Kommende Veranstaltungen
97
+ live: Live
98
+ </i18n>
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <span v-if="span instanceof String">
3
+ {{ span }}
4
+ </span>
5
+ <span v-else-if="Array.isArray(span) && span.length === 1">
6
+ {{ span[0] }}
7
+ </span>
8
+ <ol v-else-if="Array.isArray(span)" class="list-decimal">
9
+ <li v-for="spanItem in span" :key="spanItem.toString()">
10
+ {{ spanItem }}
11
+ </li>
12
+ </ol>
13
+ </template>
14
+
15
+ <script setup lang="ts">
16
+ export interface Props {
17
+ span: Array<string | Array<string>>
18
+ }
19
+ withDefaults(defineProps<Props>(), {})
20
+ </script>
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <div
3
+ class="flex h-full items-center justify-center"
4
+ :title="t('globalStatusLoading')"
5
+ >
6
+ <div class="flex items-center justify-center w-1/2">
7
+ <slot />
8
+ </div>
9
+ </div>
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ const { t } = useI18n()
14
+ </script>
@@ -0,0 +1,12 @@
1
+ <template>
2
+ <VioLoaderIndicator>
3
+ <div
4
+ class="w-1/2 aspect-square animate-ping rounded-full bg-gray-500"
5
+ :title="t('globalStatusLoading')"
6
+ />
7
+ </VioLoaderIndicator>
8
+ </template>
9
+
10
+ <script setup lang="ts">
11
+ const { t } = useI18n()
12
+ </script>
@@ -0,0 +1,24 @@
1
+ <template>
2
+ <VioLoaderIndicator>
3
+ <svg
4
+ class="animate-spin text-black dark:text-white"
5
+ xmlns="http://www.w3.org/2000/svg"
6
+ fill="none"
7
+ viewBox="0 0 24 24"
8
+ >
9
+ <circle
10
+ class="opacity-25"
11
+ cx="12"
12
+ cy="12"
13
+ r="10"
14
+ stroke="currentColor"
15
+ stroke-width="4"
16
+ />
17
+ <path
18
+ class="opacity-75"
19
+ fill="currentColor"
20
+ d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
21
+ />
22
+ </svg>
23
+ </VioLoaderIndicator>
24
+ </template>
@@ -9,13 +9,13 @@
9
9
  <br />
10
10
  </template>
11
11
  <template #city>
12
- {{ appConfig.legalNotice.tmg.address.city }}
12
+ {{ appConfig.vio.pages.legalNotice.tmg.address.city }}
13
13
  </template>
14
14
  <template #name>
15
- {{ appConfig.legalNotice.tmg.address.name }}
15
+ {{ appConfig.vio.pages.legalNotice.tmg.address.name }}
16
16
  </template>
17
17
  <template #street>
18
- {{ appConfig.legalNotice.tmg.address.street }}
18
+ {{ appConfig.vio.pages.legalNotice.tmg.address.street }}
19
19
  </template>
20
20
  </i18n-t>
21
21
  </address>
@@ -24,7 +24,9 @@
24
24
  <p>
25
25
  <slot v-if="$slots.contactEmail" name="contactEmail" />
26
26
  <span v-else>
27
- {{ t('email', { email: appConfig.legalNotice.contact.email }) }}
27
+ {{
28
+ t('email', { email: appConfig.vio.pages.legalNotice.contact.email })
29
+ }}
28
30
  </span>
29
31
  </p>
30
32
 
@@ -36,13 +38,13 @@
36
38
  <br />
37
39
  </template>
38
40
  <template #city>
39
- {{ appConfig.legalNotice.responsibility.address.city }}
41
+ {{ appConfig.vio.pages.legalNotice.responsibility.address.city }}
40
42
  </template>
41
43
  <template #name>
42
- {{ appConfig.legalNotice.responsibility.address.name }}
44
+ {{ appConfig.vio.pages.legalNotice.responsibility.address.name }}
43
45
  </template>
44
46
  <template #street>
45
- {{ appConfig.legalNotice.responsibility.address.street }}
47
+ {{ appConfig.vio.pages.legalNotice.responsibility.address.street }}
46
48
  </template>
47
49
  </i18n-t>
48
50
  </address>
@@ -73,7 +75,7 @@ const { t } = useI18n()
73
75
  const title = t('title')
74
76
 
75
77
  // initialization
76
- useSeoMeta({ title })
78
+ useServerSeoMeta({ title })
77
79
  </script>
78
80
 
79
81
  <i18n lang="yaml">
@@ -64,14 +64,21 @@
64
64
  <br />
65
65
  </template>
66
66
  <template #city>
67
- {{ appConfig.privacyPolicy.hostingCdn.external.address.city }}
67
+ {{
68
+ appConfig.vio.pages.privacyPolicy.hostingCdn.external
69
+ .address.city
70
+ }}
68
71
  </template>
69
72
  <template #name>
70
- {{ appConfig.privacyPolicy.hostingCdn.external.address.name }}
73
+ {{
74
+ appConfig.vio.pages.privacyPolicy.hostingCdn.external
75
+ .address.name
76
+ }}
71
77
  </template>
72
78
  <template #street>
73
79
  {{
74
- appConfig.privacyPolicy.hostingCdn.external.address.street
80
+ appConfig.vio.pages.privacyPolicy.hostingCdn.external
81
+ .address.street
75
82
  }}
76
83
  </template>
77
84
  </i18n-t>
@@ -109,29 +116,29 @@
109
116
  </template>
110
117
  <template #city>
111
118
  {{
112
- appConfig.privacyPolicy.mandatoryInfo.responsible.address
113
- .city
119
+ appConfig.vio.pages.privacyPolicy.mandatoryInfo.responsible
120
+ .address.city
114
121
  }}
115
122
  </template>
116
123
  <template #email>
117
124
  {{
118
125
  t('email', {
119
126
  email:
120
- appConfig.privacyPolicy.mandatoryInfo.responsible
121
- .address.email,
127
+ appConfig.vio.pages.privacyPolicy.mandatoryInfo
128
+ .responsible.address.email,
122
129
  })
123
130
  }}
124
131
  </template>
125
132
  <template #name>
126
133
  {{
127
- appConfig.privacyPolicy.mandatoryInfo.responsible.address
128
- .name
134
+ appConfig.vio.pages.privacyPolicy.mandatoryInfo.responsible
135
+ .address.name
129
136
  }}
130
137
  </template>
131
138
  <template #street>
132
139
  {{
133
- appConfig.privacyPolicy.mandatoryInfo.responsible.address
134
- .street
140
+ appConfig.vio.pages.privacyPolicy.mandatoryInfo.responsible
141
+ .address.street
135
142
  }}
136
143
  </template>
137
144
  </i18n-t>
@@ -502,7 +509,7 @@ const { t } = useI18n()
502
509
  const title = t('title')
503
510
 
504
511
  // initialization
505
- useSeoMeta({ title })
512
+ useServerSeoMeta({ title })
506
513
  </script>
507
514
 
508
515
  <i18n lang="yaml">
@@ -1,29 +1,23 @@
1
1
  export const useAppLayout = () => {
2
2
  const appConfig = useAppConfig()
3
+ const siteConfig = useSiteConfig()
3
4
 
4
- useHead({
5
+ useServerHeadSafe({
5
6
  ...useLocaleHead({ addSeoAttributes: true }).value,
6
7
  bodyAttrs: {
7
8
  class:
8
9
  'bg-background-bright dark:bg-background-dark font-sans text-text-dark dark:text-text-bright',
9
10
  },
10
- ...(appConfig.themeColor
11
- ? {
12
- meta: [
13
- {
14
- content: appConfig.themeColor,
15
- name: 'msapplication-TileColor',
16
- },
17
- {
18
- content: appConfig.themeColor,
19
- name: 'theme-color',
20
- },
21
- ],
22
- }
23
- : {}),
24
11
  })
25
12
 
26
- if (appConfig.seoMeta) {
27
- useSeoMeta(appConfig.seoMeta)
28
- }
13
+ useServerSeoMeta({
14
+ msapplicationTileColor: appConfig.vio.themeColor,
15
+ themeColor: appConfig.vio.themeColor,
16
+ titleTemplate: (titleChunk) => {
17
+ return titleChunk && titleChunk !== siteConfig.name
18
+ ? `${titleChunk} ${siteConfig.titleSeparator} ${siteConfig.name}`
19
+ : siteConfig.name
20
+ },
21
+ ...(appConfig.vio.seoMeta ? appConfig.vio.seoMeta : {}),
22
+ })
29
23
  }
@@ -0,0 +1,17 @@
1
+ import { Dayjs } from 'dayjs'
2
+
3
+ export const useDateTime = () => {
4
+ const event = useRequestEvent()
5
+ const { $dayjs } = useNuxtApp()
6
+ const timezoneCookie = useCookie(TIMEZONE_COOKIE_NAME)
7
+
8
+ const timezoneHeader = event?.node.req.headers[TIMEZONE_HEADER_KEY]
9
+ const timezone =
10
+ timezoneHeader && !Array.isArray(timezoneHeader)
11
+ ? timezoneHeader
12
+ : timezoneCookie.value || undefined
13
+
14
+ return (dateTime?: string | number | Dayjs | Date | null) =>
15
+ // @ts-ignore `tz` should be part of `$dayjs` (https://github.com/iamkun/dayjs/issues/2106)
16
+ $dayjs(dateTime).tz(timezone)
17
+ }
@@ -1,49 +1,21 @@
1
1
  export const useFavicons = () => {
2
2
  const appConfig = useAppConfig()
3
3
 
4
- useHead({
4
+ useServerHeadSafe({
5
5
  link: [
6
6
  {
7
- href: '/assets/static/favicon/apple-touch-icon.png?v=bOXMwoKlJr',
8
- rel: 'apple-touch-icon',
9
- sizes: '180x180',
10
- },
11
- {
12
- href: '/assets/static/favicon/favicon-16x16.png?v=bOXMwoKlJr',
13
- rel: 'icon',
14
- sizes: '16x16',
15
- type: 'image/png',
16
- },
17
- {
18
- href: '/assets/static/favicon/favicon-32x32.png?v=bOXMwoKlJr',
19
- rel: 'icon',
20
- sizes: '32x32',
21
- type: 'image/png',
22
- },
23
- {
24
- href: '/favicon.ico',
25
- rel: 'icon',
26
- type: 'image/x-icon',
27
- },
28
- {
29
- href: '/assets/static/favicon/site.webmanifest?v=bOXMwoKlJr',
7
+ href: `/assets/static/favicon/site.webmanifest?v=${CACHE_VERSION}`,
30
8
  rel: 'manifest',
31
9
  },
32
10
  {
33
- color: appConfig.themeColor,
34
- href: '/assets/static/favicon/safari-pinned-tab.svg?v=bOXMwoKlJr',
11
+ color: appConfig.vio.themeColor,
12
+ href: `/assets/static/favicon/safari-pinned-tab.svg?v=${CACHE_VERSION}`,
35
13
  rel: 'mask-icon',
36
14
  },
37
15
  {
38
- href: '/favicon.ico?v=bOXMwoKlJr',
16
+ href: `/favicon.ico?v=${CACHE_VERSION}`,
39
17
  rel: 'shortcut icon',
40
18
  },
41
19
  ],
42
- meta: [
43
- {
44
- content: '/assets/static/favicon/browserconfig.xml?v=bOXMwoKlJr',
45
- name: 'msapplication-config',
46
- },
47
- ],
48
20
  })
49
21
  }
@@ -0,0 +1,17 @@
1
+ import { consola } from 'consola'
2
+ import Swal from 'sweetalert2'
3
+ import { Ref } from 'vue'
4
+
5
+ export const useFireError = () => {
6
+ const { t } = useI18n()
7
+
8
+ return ({ error }: { error: Error }, api?: Ref<any>) => {
9
+ Swal.fire({
10
+ icon: 'error',
11
+ title: t('globalStatusError'),
12
+ text: error.message,
13
+ })
14
+ api?.value.errors.push(error)
15
+ consola.error(error)
16
+ }
17
+ }
@@ -0,0 +1,21 @@
1
+ export const useGetServiceHref = () => {
2
+ const host = useHost()
3
+ const runtimeConfig = useRuntimeConfig()
4
+
5
+ return ({
6
+ isSsr = true,
7
+ name,
8
+ port,
9
+ }: {
10
+ isSsr?: boolean
11
+ name?: string
12
+ port?: number
13
+ }) =>
14
+ getServiceHref({
15
+ host,
16
+ isSsr,
17
+ name,
18
+ port,
19
+ stagingHost: runtimeConfig.public.stagingHost,
20
+ })
21
+ }
@@ -0,0 +1,21 @@
1
+ import { defu } from 'defu'
2
+ import type { ComputedRef } from 'vue'
3
+
4
+ export const useHeadDefault = ({
5
+ extension,
6
+ title,
7
+ }: {
8
+ extension?: Parameters<typeof useServerSeoMeta>[0]
9
+ title: string | ComputedRef<string>
10
+ }) => {
11
+ const attrs = useAttrs()
12
+
13
+ const defaults: Parameters<typeof useServerSeoMeta>[0] = {
14
+ msapplicationConfig: `/assets/static/favicon/browserconfig.xml?v=${CACHE_VERSION}`,
15
+ title,
16
+ twitterDescription: attrs['site-description'] as string,
17
+ twitterTitle: title,
18
+ }
19
+
20
+ useServerSeoMeta(defu(extension, defaults))
21
+ }
@@ -0,0 +1,23 @@
1
+ export const usePolyfills = () => {
2
+ const polyfills =
3
+ 'https://polyfill.io/v3/polyfill.min.js?features=Promise&flags=gated'
4
+
5
+ useServerHead({
6
+ link: [
7
+ {
8
+ rel: 'preload',
9
+ href: polyfills,
10
+ crossorigin: 'anonymous',
11
+ as: 'script',
12
+ 'data-testid': 'polyfill-preload',
13
+ },
14
+ ],
15
+ script: [
16
+ {
17
+ src: polyfills,
18
+ crossorigin: 'anonymous',
19
+ 'data-testid': 'polyfill-script',
20
+ },
21
+ ],
22
+ })
23
+ }
@@ -0,0 +1,10 @@
1
+ import { ofetch } from 'ofetch'
2
+
3
+ export const useStrapiFetch = () => {
4
+ const getServiceHref = useGetServiceHref()
5
+
6
+ // TODO: switch back to $fetch (https://github.com/unjs/nitro/issues/470)
7
+ return ofetch.create({
8
+ baseURL: getServiceHref({ name: 'creal_strapi', port: 1337 }) + '/api',
9
+ })
10
+ }
package/error.vue CHANGED
@@ -16,8 +16,11 @@ export interface Props {
16
16
  error: NuxtError
17
17
  }
18
18
  const props = withDefaults(defineProps<Props>(), {})
19
+ const errorProp = toRef(() => props.error)
19
20
 
20
- useHead({
21
- title: `${props.error.statusCode} - ${props.error.message}`,
21
+ // initialization
22
+ useAppLayout()
23
+ useServerHeadSafe({
24
+ title: `${errorProp.value.statusCode} - ${errorProp.value.message}`,
22
25
  })
23
26
  </script>
package/locales/de.json CHANGED
@@ -1,3 +1,9 @@
1
1
  {
2
- "globalLoading": "Lade..."
2
+ "globalPlaceholderUrl": "https://websei.te",
3
+ "globalStatusError": "Fehler",
4
+ "globalStatusLoading": "Lade...",
5
+ "globalValidationFailed": "Bitte überprüfe deine Eingaben 🙈",
6
+ "globalValidationFormatUrlHttps": "Muss mit \"https://\" beginnen",
7
+ "globalValidationLength": "Zu lang",
8
+ "globalValidationRequired": "Pflichtfeld"
3
9
  }
package/locales/en.json CHANGED
@@ -1,3 +1,9 @@
1
1
  {
2
- "globalLoading": "Loading..."
2
+ "globalPlaceholderUrl": "https://websi.te",
3
+ "globalStatusError": "Error",
4
+ "globalStatusLoading": "Loading...",
5
+ "globalValidationFailed": "Please check your input 🙈",
6
+ "globalValidationFormatUrlHttps": "Must start with \"https://\"",
7
+ "globalValidationLength": "Too long",
8
+ "globalValidationRequired": "Required"
3
9
  }