@shopbite-de/storefront 1.5.3 → 1.6.1
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.
- package/.env.example +6 -1
- package/LICENSE +21 -0
- package/README.md +81 -0
- package/app/components/Address/Fields.vue +128 -0
- package/app/components/Checkout/PaymentAndDelivery.vue +49 -27
- package/app/components/Header.vue +26 -13
- package/app/components/User/LoginForm.vue +32 -11
- package/app/components/User/RegistrationForm.vue +105 -180
- package/app/composables/useAddressAutocomplete.ts +84 -0
- package/app/composables/useAddressValidation.ts +95 -0
- package/app/composables/useValidCitiesForDelivery.ts +12 -0
- package/app/pages/[...all].vue +28 -0
- package/app/pages/index.vue +4 -0
- package/app/pages/menu/[...all].vue +52 -0
- package/app/validation/registrationSchema.ts +105 -124
- package/content/{unternehmen/impressum.md → impressum.md} +5 -0
- package/content/index.yml +2 -1
- package/content/unternehmen/agb.md +5 -0
- package/content/unternehmen/datenschutz.md +5 -0
- package/content/unternehmen/zahlung-und-versand.md +34 -0
- package/content.config.ts +6 -2
- package/eslint.config.mjs +5 -3
- package/nuxt.config.ts +33 -22
- package/package.json +2 -1
- package/public/card.png +0 -0
- package/server/api/address/autocomplete.get.ts +33 -0
- package/test/nuxt/AddressFields.test.ts +284 -0
- package/test/nuxt/Header.test.ts +124 -0
- package/test/nuxt/LoginForm.test.ts +141 -0
- package/test/nuxt/PaymentAndDelivery.test.ts +78 -0
- package/test/nuxt/RegistrationForm.test.ts +255 -0
- package/test/nuxt/RegistrationValidation.test.ts +39 -0
- package/test/nuxt/registrationSchema.test.ts +242 -0
- package/test/nuxt/useAddressAutocomplete.test.ts +161 -0
- package/app/pages/unternehmen/[slug].vue +0 -66
|
@@ -1,14 +1,47 @@
|
|
|
1
1
|
// schemas/registrationSchema.ts
|
|
2
2
|
import * as z from "zod";
|
|
3
3
|
|
|
4
|
+
const baseAddressSchema = z.object({
|
|
5
|
+
firstName: z.string().optional(),
|
|
6
|
+
lastName: z.string().optional(),
|
|
7
|
+
company: z.string().optional(),
|
|
8
|
+
department: z.string().optional(),
|
|
9
|
+
salutationId: z.string().optional(),
|
|
10
|
+
street: z
|
|
11
|
+
.string()
|
|
12
|
+
.min(1, { message: "Bitte geben Sie Ihre Straße und Hausnummer an." })
|
|
13
|
+
.refine((val) => /[0-9]/.test(val), {
|
|
14
|
+
message: "Bitte geben Sie Ihre Straße und Hausnummer an.",
|
|
15
|
+
}),
|
|
16
|
+
additionalAddressLine1: z.string().optional(),
|
|
17
|
+
zipcode: z.string().optional(),
|
|
18
|
+
city: z.string().min(1, {
|
|
19
|
+
message: "Bitte geben Sie Ihren Ort an.",
|
|
20
|
+
}),
|
|
21
|
+
countryId: z.string().min(1, { message: "Bitte wählen Sie ein Land aus." }),
|
|
22
|
+
phoneNumber: z.string().min(7, {
|
|
23
|
+
message: "Bitte geben Sie eine gültige Telefonnummer an (mind. 7 Zeichen).",
|
|
24
|
+
}),
|
|
25
|
+
});
|
|
26
|
+
|
|
4
27
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
28
|
export const createRegistrationSchema = (state: any) =>
|
|
6
29
|
z.object({
|
|
7
|
-
accountType: z.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
30
|
+
accountType: z.enum(["private", "business"], {
|
|
31
|
+
errorMap: () => ({ message: "Bitte wählen Sie einen Kontotyp aus." }),
|
|
32
|
+
}),
|
|
33
|
+
email: z.string().email("Bitte geben Sie eine gültige E-Mail-Adresse ein."),
|
|
34
|
+
firstName: z
|
|
35
|
+
.string()
|
|
36
|
+
.min(1, { message: "Bitte geben Sie Ihren Vornamen an." }),
|
|
37
|
+
lastName: z
|
|
38
|
+
.string()
|
|
39
|
+
.min(1, { message: "Bitte geben Sie Ihren Nachnamen an." }),
|
|
11
40
|
guest: z.boolean(),
|
|
41
|
+
acceptedDataProtection: z.boolean().refine((val) => val, {
|
|
42
|
+
message: "Bitte akzeptieren Sie die Datenschutzbestimmungen.",
|
|
43
|
+
}),
|
|
44
|
+
storefrontUrl: z.string().optional(),
|
|
12
45
|
password: z
|
|
13
46
|
.string()
|
|
14
47
|
.optional()
|
|
@@ -17,7 +50,7 @@ export const createRegistrationSchema = (state: any) =>
|
|
|
17
50
|
return state.guest || (val && val.length >= 8);
|
|
18
51
|
},
|
|
19
52
|
{
|
|
20
|
-
message: "
|
|
53
|
+
message: "Das Passwort muss mindestens 8 Zeichen lang sein.",
|
|
21
54
|
},
|
|
22
55
|
),
|
|
23
56
|
passwordConfirm: z
|
|
@@ -28,129 +61,77 @@ export const createRegistrationSchema = (state: any) =>
|
|
|
28
61
|
return state.guest || val === state.password;
|
|
29
62
|
},
|
|
30
63
|
{
|
|
31
|
-
message: "
|
|
64
|
+
message: "Die Passwörter stimmen nicht überein.",
|
|
32
65
|
},
|
|
33
66
|
),
|
|
34
|
-
billingAddress:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
),
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
!state.isShippingAddressDifferent ||
|
|
99
|
-
(val !== undefined && val !== "")
|
|
100
|
-
);
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
message: "Erforderlich.",
|
|
104
|
-
},
|
|
105
|
-
),
|
|
106
|
-
department: z.string().optional(),
|
|
107
|
-
phoneNumber: z
|
|
108
|
-
.string()
|
|
109
|
-
.optional()
|
|
110
|
-
.refine(
|
|
111
|
-
(val) => {
|
|
112
|
-
return (
|
|
113
|
-
!state.isShippingAddressDifferent ||
|
|
114
|
-
(val !== undefined && val !== "")
|
|
115
|
-
);
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
message: "Erforderlich.",
|
|
119
|
-
},
|
|
120
|
-
),
|
|
121
|
-
street: z
|
|
122
|
-
.string()
|
|
123
|
-
.optional()
|
|
124
|
-
.refine(
|
|
125
|
-
(val) => {
|
|
126
|
-
return (
|
|
127
|
-
!state.isShippingAddressDifferent ||
|
|
128
|
-
(val !== undefined && val !== "")
|
|
129
|
-
);
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
message: "Erforderlich.",
|
|
133
|
-
},
|
|
134
|
-
),
|
|
135
|
-
zipcode: z.string().min(1).optional(),
|
|
136
|
-
city: z
|
|
137
|
-
.string()
|
|
138
|
-
.optional()
|
|
139
|
-
.refine(
|
|
140
|
-
(val) => {
|
|
141
|
-
return (
|
|
142
|
-
!state.isShippingAddressDifferent ||
|
|
143
|
-
(val !== undefined && val !== "")
|
|
144
|
-
);
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
message: "Erforderlich.",
|
|
148
|
-
},
|
|
149
|
-
),
|
|
150
|
-
countryId: z.string().min(1),
|
|
151
|
-
}),
|
|
67
|
+
billingAddress: baseAddressSchema.refine(
|
|
68
|
+
(data) => {
|
|
69
|
+
return (
|
|
70
|
+
state.accountType !== "business" ||
|
|
71
|
+
(data.company !== undefined && data.company !== "")
|
|
72
|
+
);
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
message: "Als Geschäftskunde ist der Firmenname ein Pflichtfeld.",
|
|
76
|
+
path: ["company"],
|
|
77
|
+
},
|
|
78
|
+
),
|
|
79
|
+
shippingAddress: baseAddressSchema
|
|
80
|
+
.extend({
|
|
81
|
+
firstName: z.string().optional(),
|
|
82
|
+
lastName: z.string().optional(),
|
|
83
|
+
company: z.string().optional(),
|
|
84
|
+
phoneNumber: z.string().optional(),
|
|
85
|
+
street: z.string().optional(),
|
|
86
|
+
city: z.string().optional(),
|
|
87
|
+
zipcode: z.string().optional(),
|
|
88
|
+
countryId: z.string().optional(),
|
|
89
|
+
})
|
|
90
|
+
.superRefine((data, ctx) => {
|
|
91
|
+
if (!state.isShippingAddressDifferent) return;
|
|
92
|
+
|
|
93
|
+
const requiredFields: (keyof typeof data)[] = [
|
|
94
|
+
"firstName",
|
|
95
|
+
"lastName",
|
|
96
|
+
"company",
|
|
97
|
+
"phoneNumber",
|
|
98
|
+
"street",
|
|
99
|
+
"city",
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
const fieldMessages: Record<string, string> = {
|
|
103
|
+
firstName: "Bitte geben Sie den Vornamen für die Lieferadresse an.",
|
|
104
|
+
lastName: "Bitte geben Sie den Nachnamen für die Lieferadresse an.",
|
|
105
|
+
company: "Bitte geben Sie den Firmennamen für die Lieferadresse an.",
|
|
106
|
+
phoneNumber:
|
|
107
|
+
"Bitte geben Sie eine Telefonnummer für die Lieferadresse an.",
|
|
108
|
+
street: "Bitte geben Sie die Straße für die Lieferadresse an.",
|
|
109
|
+
city: "Bitte geben Sie den Ort für die Lieferadresse an.",
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
requiredFields.forEach((field) => {
|
|
113
|
+
if (field === "company" && state.accountType !== "business") return;
|
|
114
|
+
|
|
115
|
+
if (!data[field] || data[field] === "") {
|
|
116
|
+
ctx.addIssue({
|
|
117
|
+
code: z.ZodIssueCode.custom,
|
|
118
|
+
message: fieldMessages[field] || "Dieses Feld ist erforderlich.",
|
|
119
|
+
path: [field],
|
|
120
|
+
});
|
|
121
|
+
} else if (field === "street" && !/[0-9]/.test(data.street || "")) {
|
|
122
|
+
ctx.addIssue({
|
|
123
|
+
code: z.ZodIssueCode.custom,
|
|
124
|
+
message: "Bitte geben Sie Ihre Straße und Hausnummer an.",
|
|
125
|
+
path: ["street"],
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
})
|
|
130
|
+
.optional(),
|
|
152
131
|
});
|
|
153
132
|
|
|
154
133
|
export type RegistrationSchema = z.infer<
|
|
155
134
|
ReturnType<typeof createRegistrationSchema>
|
|
156
135
|
>;
|
|
136
|
+
|
|
137
|
+
export type AddressSchema = z.infer<typeof baseAddressSchema>;
|
package/content/index.yml
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
seo:
|
|
2
|
-
title: ShopBite –
|
|
2
|
+
title: ShopBite – Demo Store
|
|
3
3
|
description: Dein eigenes Bestellsystem ohne Provisionen, ohne monatliche Kosten – 100% Open Source und individuell anpassbar. Perfekt für Pizzerien, Imbisse und Lieferdienste.
|
|
4
|
+
image: /card.png
|
|
4
5
|
title: ShopBite
|
|
5
6
|
description: Reduziere Kosten und steigere deinen Umsatz
|
|
6
7
|
hero:
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Zahlungs- und Lieferinformationen
|
|
3
|
+
description: Zahlungs- und Lieferinformationen
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Zahlungs- und Lieferinformationen
|
|
7
|
+
|
|
8
|
+
### Liefermethoden
|
|
9
|
+
|
|
10
|
+
Wir bieten Ihnen zwei Möglichkeiten, Ihre Bestellung zu erhalten:
|
|
11
|
+
|
|
12
|
+
- **Lieferung:** Wir bringen Ihre Bestellung direkt zu Ihnen nach Hause (beachten Sie bitte unsere Liefergebiete).
|
|
13
|
+
- **Abholung:** Sie können Ihre Bestellung auch direkt bei uns abholen (Kantstraße 6, 63179 Obertshausen).
|
|
14
|
+
|
|
15
|
+
### Zahlungsmöglichkeiten
|
|
16
|
+
|
|
17
|
+
- **Bei Lieferung:** Die Zahlung erfolgt ausschließlich **bar**.
|
|
18
|
+
- **Bei Abholung:** Sie können bar oder elektronisch mit **EC-Karte** bezahlen.
|
|
19
|
+
|
|
20
|
+
### Lieferbedingungen
|
|
21
|
+
|
|
22
|
+
Wir liefern ausschließlich in folgende Gebiete:
|
|
23
|
+
|
|
24
|
+
- **63179 Obertshausen** (Stadtteile Obertshausen und Hausen)
|
|
25
|
+
- **63165 Mühlheim** (Stadtteil Lämmerspiel)
|
|
26
|
+
|
|
27
|
+
### Lieferkosten
|
|
28
|
+
|
|
29
|
+
- **Ab 15,00 € Bestellwert:** Lieferung frei Haus (versandkostenfrei).
|
|
30
|
+
- **Unter 15,00 € Bestellwert:** Wir erheben eine Lieferpauschale von **2,00 €**.
|
|
31
|
+
|
|
32
|
+
### Lieferzeit
|
|
33
|
+
|
|
34
|
+
Die Lieferzeit beträgt in der Regel ca. **30 Minuten**. Bitte beachten Sie, dass es zu Stoßzeiten zu Abweichungen kommen kann.
|
package/content.config.ts
CHANGED
|
@@ -131,9 +131,13 @@ export default defineContentConfig({
|
|
|
131
131
|
}),
|
|
132
132
|
}),
|
|
133
133
|
}),
|
|
134
|
-
|
|
135
|
-
source: "
|
|
134
|
+
landingpages: defineCollection({
|
|
135
|
+
source: "**/*.md",
|
|
136
136
|
type: "page",
|
|
137
|
+
schema: z.object({
|
|
138
|
+
title: z.string().min(1),
|
|
139
|
+
description: z.string().optional(),
|
|
140
|
+
}),
|
|
137
141
|
}),
|
|
138
142
|
},
|
|
139
143
|
});
|
package/eslint.config.mjs
CHANGED
|
@@ -3,6 +3,8 @@ import withNuxt from './.nuxt/eslint.config.mjs'
|
|
|
3
3
|
|
|
4
4
|
export default withNuxt({
|
|
5
5
|
rules: {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
"vue/no-watch-after-await": "error",
|
|
7
|
+
"vue/no-lifecycle-after-await": "error",
|
|
8
|
+
"vue/multi-word-component-names": "off",
|
|
9
|
+
},
|
|
10
|
+
});
|
package/nuxt.config.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export default defineNuxtConfig({
|
|
3
3
|
app: {
|
|
4
4
|
head: {
|
|
5
|
-
title: "ShopBite
|
|
5
|
+
title: "ShopBite – Kostenloses Online-Bestellsystem für Gastronomie",
|
|
6
6
|
htmlAttrs: {
|
|
7
7
|
lang: "de",
|
|
8
8
|
},
|
|
@@ -11,18 +11,20 @@ export default defineNuxtConfig({
|
|
|
11
11
|
{ name: "viewport", content: "width=device-width, initial-scale=1" },
|
|
12
12
|
{
|
|
13
13
|
name: "description",
|
|
14
|
-
content:
|
|
14
|
+
content:
|
|
15
|
+
"Dein eigenes Bestellsystem ohne Provisionen, ohne monatliche Kosten – 100% Open Source und individuell anpassbar. Perfekt für Pizzerien, Imbisse und Lieferdienste.",
|
|
15
16
|
},
|
|
16
17
|
{
|
|
17
18
|
property: "og:title",
|
|
18
|
-
content:
|
|
19
|
+
content:
|
|
20
|
+
"Dein eigenes Bestellsystem ohne Provisionen, ohne monatliche Kosten – 100% Open Source und individuell anpassbar. Perfekt für Pizzerien, Imbisse und Lieferdienste.",
|
|
19
21
|
},
|
|
20
22
|
{
|
|
21
23
|
property: "og:description",
|
|
22
24
|
content: "Italienisch-deutsche Küche in Obertshausen",
|
|
23
25
|
},
|
|
24
26
|
],
|
|
25
|
-
link: [{ rel: "icon", href: "/favicon.ico" }],
|
|
27
|
+
link: [{ rel: "icon", href: "/favicon.ico", type: "image/png" }],
|
|
26
28
|
},
|
|
27
29
|
},
|
|
28
30
|
colorMode: {
|
|
@@ -30,12 +32,6 @@ export default defineNuxtConfig({
|
|
|
30
32
|
},
|
|
31
33
|
robots: {
|
|
32
34
|
disallow: [
|
|
33
|
-
"/unternehmen/impressum",
|
|
34
|
-
"/unternehmen/datenschutz",
|
|
35
|
-
"/unternehmen/agb",
|
|
36
|
-
"/impressum",
|
|
37
|
-
"/datenschutz",
|
|
38
|
-
"/agb",
|
|
39
35
|
"/merkliste",
|
|
40
36
|
"/passwort-vergessen",
|
|
41
37
|
"/account/recover/password",
|
|
@@ -45,6 +41,7 @@ export default defineNuxtConfig({
|
|
|
45
41
|
runtimeConfig: {
|
|
46
42
|
shopware: {},
|
|
47
43
|
apiClientConfig: {},
|
|
44
|
+
geoapifyApiKey: "",
|
|
48
45
|
public: {
|
|
49
46
|
site: {
|
|
50
47
|
name: "ShopBite",
|
|
@@ -59,15 +56,6 @@ export default defineNuxtConfig({
|
|
|
59
56
|
},
|
|
60
57
|
|
|
61
58
|
routeRules: {
|
|
62
|
-
"/impressum": {
|
|
63
|
-
redirect: "/unternehmen/impressum",
|
|
64
|
-
},
|
|
65
|
-
"/datenschutz": {
|
|
66
|
-
redirect: "/unternehmen/datenschutz",
|
|
67
|
-
},
|
|
68
|
-
"/agb": {
|
|
69
|
-
redirect: "/unternehmen/agb",
|
|
70
|
-
},
|
|
71
59
|
"/merkliste": {
|
|
72
60
|
ssr: false,
|
|
73
61
|
},
|
|
@@ -92,10 +80,8 @@ export default defineNuxtConfig({
|
|
|
92
80
|
"@vite-pwa/nuxt",
|
|
93
81
|
"@sentry/nuxt/module",
|
|
94
82
|
"@nuxt/ui",
|
|
83
|
+
"@nuxt/scripts",
|
|
95
84
|
"@nuxtjs/plausible",
|
|
96
|
-
...(process.env.NODE_ENV === "development"
|
|
97
|
-
? ["@nuxt/test-utils/module", "@nuxt/eslint"]
|
|
98
|
-
: []),
|
|
99
85
|
],
|
|
100
86
|
|
|
101
87
|
plausible: {
|
|
@@ -150,4 +136,29 @@ export default defineNuxtConfig({
|
|
|
150
136
|
experimental: {
|
|
151
137
|
asyncContext: true,
|
|
152
138
|
},
|
|
139
|
+
$development: {
|
|
140
|
+
modules: [
|
|
141
|
+
"@shopware/nuxt-module",
|
|
142
|
+
"@nuxt/image",
|
|
143
|
+
"@nuxt/content",
|
|
144
|
+
"@nuxtjs/robots",
|
|
145
|
+
"@vite-pwa/nuxt",
|
|
146
|
+
"@sentry/nuxt/module",
|
|
147
|
+
"@nuxt/ui",
|
|
148
|
+
"@nuxt/scripts",
|
|
149
|
+
"@nuxtjs/plausible",
|
|
150
|
+
"@nuxt/test-utils/module",
|
|
151
|
+
"@nuxt/eslint",
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
$production: {
|
|
155
|
+
scripts: {
|
|
156
|
+
registry: {
|
|
157
|
+
matomoAnalytics: {
|
|
158
|
+
matomoUrl: "",
|
|
159
|
+
siteId: "",
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
},
|
|
153
164
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shopbite-de/storefront",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"main": "nuxt.config.ts",
|
|
5
5
|
"description": "Shopware storefront for food delivery shops",
|
|
6
6
|
"keywords": [
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"@iconify-json/simple-icons": "^1.2.59",
|
|
21
21
|
"@nuxt/content": "^3.8.2",
|
|
22
22
|
"@nuxt/image": "^2.0.0",
|
|
23
|
+
"@nuxt/scripts": "0.13.2",
|
|
23
24
|
"@nuxt/ui": "^4.1.0",
|
|
24
25
|
"@nuxtjs/plausible": "2.0.1",
|
|
25
26
|
"@nuxtjs/robots": "^5.5.6",
|
package/public/card.png
ADDED
|
Binary file
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export default defineEventHandler(async (event) => {
|
|
2
|
+
const config = useRuntimeConfig();
|
|
3
|
+
const apiKey = config.geoapifyApiKey;
|
|
4
|
+
const query = getQuery(event);
|
|
5
|
+
|
|
6
|
+
if (!apiKey) {
|
|
7
|
+
return { features: [] };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { text, lang, limit, filter } = query;
|
|
11
|
+
|
|
12
|
+
if (!text) {
|
|
13
|
+
return { features: [] };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const geoapifyUrl = new URL(
|
|
17
|
+
"https://api.geoapify.com/v1/geocode/autocomplete",
|
|
18
|
+
);
|
|
19
|
+
geoapifyUrl.searchParams.set("apiKey", apiKey);
|
|
20
|
+
geoapifyUrl.searchParams.set("text", text as string);
|
|
21
|
+
if (lang) geoapifyUrl.searchParams.set("lang", lang as string);
|
|
22
|
+
if (limit) geoapifyUrl.searchParams.set("limit", limit as string);
|
|
23
|
+
if (filter) geoapifyUrl.searchParams.set("filter", filter as string);
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
return await $fetch(geoapifyUrl.toString());
|
|
27
|
+
} catch (error) {
|
|
28
|
+
throw createError({
|
|
29
|
+
statusCode: error.response?.status || 500,
|
|
30
|
+
statusMessage: error.message || "Error fetching address suggestions",
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
});
|