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

Sign up to get free protection for your applications and to get access to all the features.
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
  }