diff --git a/package-lock.json b/package-lock.json
index 8c43e2a..32eb2fa 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7,6 +7,10 @@
"": {
"name": "minibusservice.no",
"version": "0.0.0",
+ "dependencies": {
+ "leaflet": "^1.9.4",
+ "tailwind-merge": "^3.5.0"
+ },
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^7.0.0",
"@tailwindcss/vite": "^0.0.0-insiders.aaaefe8",
@@ -14,7 +18,6 @@
"@types/node": "^24.12.0",
"svelte": "^5.53.7",
"svelte-check": "^4.4.5",
- "tailwind-merge": "^3.5.0",
"tailwindcss": "^0.0.0-insiders.aaaefe8",
"typescript": "~5.9.3",
"vite": "^8.0.0"
@@ -1200,6 +1203,12 @@
"jiti": "lib/jiti-cli.mjs"
}
},
+ "node_modules/leaflet": {
+ "version": "1.9.4",
+ "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
+ "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==",
+ "license": "BSD-2-Clause"
+ },
"node_modules/lightningcss": {
"version": "1.32.0",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
@@ -1694,7 +1703,6 @@
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.5.0.tgz",
"integrity": "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==",
- "dev": true,
"license": "MIT",
"funding": {
"type": "github",
diff --git a/package.json b/package.json
index 673f288..49e5759 100644
--- a/package.json
+++ b/package.json
@@ -16,9 +16,12 @@
"@types/node": "^24.12.0",
"svelte": "^5.53.7",
"svelte-check": "^4.4.5",
- "tailwind-merge": "^3.5.0",
"tailwindcss": "^0.0.0-insiders.aaaefe8",
"typescript": "~5.9.3",
"vite": "^8.0.0"
+ },
+ "dependencies": {
+ "leaflet": "^1.9.4",
+ "tailwind-merge": "^3.5.0"
}
}
diff --git a/src/App.svelte b/src/App.svelte
index fe0978f..8545d9c 100644
--- a/src/App.svelte
+++ b/src/App.svelte
@@ -1,15 +1,40 @@
-
- {#snippet notfound()}
- Not found
- Sorry, the page you are looking for does not exist.
- Return to home .
- {/snippet}
-
+
+
+
+
+
+ {#snippet notfound()}
+ Not found
+
+ Sorry, the page you are looking for does not exist.
+
+ Return to home .
+ {/snippet}
+
+
+
+
+
+
+
+
diff --git a/src/Footer.svelte b/src/Footer.svelte
new file mode 100644
index 0000000..4dc49d5
--- /dev/null
+++ b/src/Footer.svelte
@@ -0,0 +1,31 @@
+
+
+
+
+ {#each Routes.footerRoutes as section}
+
+
+ {section.text}
+
+ {#each section.routes as route}
+
+
+ {route.text}
+
+
+ {/each}
+
+ {/each}
+
+ Org nr: 816 230 942
+
+ © 2026 minibusservice.no - All Rights Reserved.
+
+
diff --git a/src/Navigation.svelte b/src/Navigation.svelte
new file mode 100644
index 0000000..5d35adc
--- /dev/null
+++ b/src/Navigation.svelte
@@ -0,0 +1,138 @@
+
+
+
+
+ {#if sidebarOpen}
+
+ {/if}
+
+
+
+
+
+
+ {#each Routes.topbarRoutes as route}
+
+
+ {route.text}
+
+ {/each}
+
+
+
diff --git a/src/lib/components/ContactForm.svelte b/src/lib/components/ContactForm.svelte
index 929b773..285de50 100644
--- a/src/lib/components/ContactForm.svelte
+++ b/src/lib/components/ContactForm.svelte
@@ -1,122 +1,38 @@
-
-
-
-
-
- Spørsmål? Kontakt oss via tlf, e-post eller via skjemaet under
-
-
- Spørsmål? Kontakt oss via tlf, e-post eller via skjemaet til høyre
-
-
- Tlf: +47 45 25 61 61
-
-
- E-post: minibusstur@hotmail.com
-
-
-
-
-
-
-
+
+
+
+
+
+ Spørsmål? Kontakt oss via tlf, e-post eller via skjemaet under
+
+
+ Spørsmål? Kontakt oss via tlf, e-post eller via skjemaet til
+ høyre
+
+
+ Tlf: +47 45 25 61 61
+
+
+ E-post: minibusstur@hotmail.com
+
+
+
+
+
diff --git a/src/lib/components/MapPoint.svelte b/src/lib/components/MapPoint.svelte
index 73b8d3c..19c658a 100644
--- a/src/lib/components/MapPoint.svelte
+++ b/src/lib/components/MapPoint.svelte
@@ -1,79 +1,86 @@
-
-
-
+
+
+
diff --git a/src/lib/components/PageSelector.svelte b/src/lib/components/PageSelector.svelte
index 39dd2e3..e48c816 100644
--- a/src/lib/components/PageSelector.svelte
+++ b/src/lib/components/PageSelector.svelte
@@ -1,41 +1,42 @@
-
-
-
+
+
+
diff --git a/src/lib/components/Router.svelte b/src/lib/components/Router.svelte
index 8b5bfab..1e69613 100644
--- a/src/lib/components/Router.svelte
+++ b/src/lib/components/Router.svelte
@@ -3,6 +3,7 @@
import { onMount, type Component, type Snippet } from "svelte";
type RouteInfo = {
+ path: string;
pattern: RegExp;
paramNames: string[];
component: Component<{}>;
@@ -44,7 +45,16 @@
});
function normalizePath(path: string): string {
- return path.replace(/\/+$/, "");
+ return path.replace(/\/+$/, "").trim();
+ }
+
+ function createRoutePattern(path: string): string {
+ const normalizedPath = normalizePath(path);
+ const escapedPath = normalizedPath.replace(/[.*+?^${}()|\\/]/g, "\\$&");
+ const pathPattern = escapedPath.replace(/\[([^\]]+)\]/g, "([^/]+)");
+ const regexPattern = `^${pathPattern}\\/?$`;
+
+ return regexPattern;
}
/**
@@ -55,17 +65,13 @@
console.warn(`Route already registered for path: '${path}'.`);
}
- const params = Array.from(
- path.matchAll(/\[([^\]]+)\]/g).map((x) => x[1]),
+ const params = Array.from(path.matchAll(/\[([^\]]+)\]/g)).map(
+ (x) => x[1],
);
- const normalizedPath = normalizePath(path);
- const escapedPath = normalizedPath.replace(/[.*+?^${}()|\\/]/g, "\\$&");
- const pathPattern = escapedPath.replace(/\[([^\]]+)\]/g, "([^/]+)");
- const regexPattern = `^${pathPattern}\\/?$`;
-
routes.set(path, {
- pattern: new RegExp(regexPattern),
+ pattern: new RegExp(createRoutePattern(path)),
+ path: path,
paramNames: params,
component: component,
});
@@ -75,6 +81,19 @@
export class MissingRouteError extends RouteError {}
export class RouteFormatError extends RouteError {}
+ export function isCurrentPath(path: string): boolean {
+ if (!currentRoute) {
+ return false;
+ }
+
+ const match = path.match(currentRoute.pattern);
+ if (!match) {
+ return false;
+ }
+
+ return true;
+ }
+
/**
* Gets the value of a route parameter.
*/
@@ -178,8 +197,9 @@
function makeProxy(target: any) {
return new Proxy(target, {
apply: (target, thisArg, argArray) => {
- target.apply(thisArg, argArray);
+ const result = target.apply(thisArg, argArray);
refresh();
+ return result;
},
});
}
@@ -197,19 +217,17 @@
return;
}
- if (e.target instanceof HTMLAnchorElement) {
- if (e.target.target === "_blank") {
- return;
- }
+ const anchor = (e.target as Element)?.closest("a");
+ if (!(anchor instanceof HTMLAnchorElement)) return;
+ if (anchor.target === "_blank") return;
- const targetUrl = new URL(e.target.href, document.baseURI);
- const documentUrl = new URL(document.baseURI);
+ const targetUrl = new URL(anchor.href, document.baseURI);
+ const documentUrl = new URL(document.baseURI);
- if (targetUrl.origin == documentUrl.origin) {
- e.preventDefault();
- history.pushState({}, "", targetUrl);
- currentUrl = targetUrl;
- }
+ if (targetUrl.origin === documentUrl.origin) {
+ e.preventDefault();
+ history.pushState({}, "", targetUrl);
+ currentUrl = targetUrl;
}
}
diff --git a/src/lib/components/toast/ToastProvider.svelte b/src/lib/components/toast/ToastProvider.svelte
index 5ce0a73..52b92cb 100644
--- a/src/lib/components/toast/ToastProvider.svelte
+++ b/src/lib/components/toast/ToastProvider.svelte
@@ -1,58 +1,68 @@
-
-
-{#if $toasts.length >= 1}
-
- {#each $toasts as toastItem}
-
-
- {#if toastItem.type === 'info'}
-
- {:else if toastItem.type === 'warning'}
-
- {:else if toastItem.type === 'error'}
-
- {:else if toastItem.type === 'success'}
-
- {/if}
-
-
-
- {toastItem.text}
-
-
-
toast.dismiss(toastItem.id)} class="shrink-0">
-
-
-
-
-
- {/each}
-
-{/if}
+
+
+{#if $toasts.length >= 1}
+
+ {#each $toasts as toastItem}
+
+
+ {#if toastItem.type === "info"}
+
+ {:else if toastItem.type === "warning"}
+
+ {:else if toastItem.type === "error"}
+
+ {:else if toastItem.type === "success"}
+
+ {/if}
+
+
+
+ {toastItem.text}
+
+
+
toast.dismiss(toastItem.id)}
+ class="shrink-0"
+ aria-label="dismiss"
+ >
+
+
+
+
+
+ {/each}
+
+{/if}
diff --git a/src/lib/global/routes.ts b/src/lib/global/routes.ts
new file mode 100644
index 0000000..b79d28a
--- /dev/null
+++ b/src/lib/global/routes.ts
@@ -0,0 +1,99 @@
+import homeIcon from "../../assets/icons/home_icon.svg";
+import contactIcon from "../../assets/icons/contact_icon.svg";
+import busIcon from "../../assets/icons/bus_icon.svg";
+
+type Route = {
+ url: string;
+ text: string;
+ icon: string | null;
+ target: string | null;
+};
+
+export class Routes {
+ static home: Route = {
+ url: "/",
+ text: "Hjem",
+ icon: homeIcon,
+ target: null,
+ };
+
+ static bus: Route = {
+ url: "/bus",
+ text: "Buss",
+ icon: busIcon,
+ target: null,
+ };
+
+ static taxi: Route = {
+ url: "/taxi",
+ text: "Taxi",
+ icon: null,
+ target: null,
+ };
+
+ static accessibility: Route = {
+ url: "/accessibility",
+ text: "Tilgjengelighetsfunksjoner",
+ icon: null,
+ target: null,
+ };
+
+ static contact: Route = {
+ url: "/contact",
+ text: "Ta kontakt",
+ icon: contactIcon,
+ target: null,
+ };
+
+ static facebook: Route = {
+ url: "https://www.facebook.com/MinibusserviceSteneAS/",
+ text: "Facebook",
+ icon: null,
+ target: "_blank",
+ };
+
+ static email: Route = {
+ url: "mailto:minibusstur@hotmail.com",
+ text: "E-post",
+ icon: null,
+ target: null,
+ };
+
+ static phone: Route = {
+ url: "tel:45256161",
+ text: "Telefon",
+ icon: null,
+ target: null,
+ };
+
+ static topbarRoutes: Route[] = [Routes.home, Routes.bus, Routes.contact];
+
+ static sidebarRoutes: Route[] = [
+ Routes.home,
+ Routes.bus,
+ Routes.taxi,
+ Routes.accessibility,
+ Routes.contact,
+ ];
+
+ static footerRoutes: { text: string; routes: Route[] }[] = [
+ {
+ text: "HJELP",
+ routes: [Routes.contact],
+ },
+ {
+ text: "SIDER",
+ routes: [
+ Routes.home,
+ Routes.bus,
+ Routes.taxi,
+ Routes.accessibility,
+ Routes.contact,
+ ],
+ },
+ {
+ text: "MINIBUSSERVICE",
+ routes: [Routes.facebook, Routes.email, Routes.phone],
+ },
+ ];
+}
diff --git a/src/lib/stores/theme.svelte.ts b/src/lib/stores/theme.svelte.ts
index 6297ec1..a2f119c 100644
--- a/src/lib/stores/theme.svelte.ts
+++ b/src/lib/stores/theme.svelte.ts
@@ -1,25 +1,22 @@
import { writable } from "svelte/store";
-import { browser } from "$app/environment";
function createThemeToggler() {
let defaultValue = false;
- if (browser) {
- let savedValue = localStorage.getItem("dark_theme");
+ let savedValue = localStorage.getItem("dark_theme");
- if (savedValue) {
- defaultValue = JSON.parse(savedValue);
- } else if (
- window.matchMedia &&
- window.matchMedia("(prefers-color-scheme: dark)").matches
- ) {
- defaultValue = true;
- }
+ if (savedValue) {
+ defaultValue = JSON.parse(savedValue);
+ } else if (
+ window.matchMedia &&
+ window.matchMedia("(prefers-color-scheme: dark)").matches
+ ) {
+ defaultValue = true;
+ }
- if (defaultValue) {
- document.documentElement.classList.add("dark");
- } else {
- document.documentElement.classList.remove("dark");
- }
+ if (defaultValue) {
+ document.documentElement.style.colorScheme = "dark";
+ } else {
+ document.documentElement.style.colorScheme = "light";
}
const { subscribe, update } = writable(defaultValue);
@@ -28,15 +25,13 @@ function createThemeToggler() {
subscribe,
set: (value: boolean) => {
update(() => value);
- if (browser) {
- if (value) {
- document.documentElement.classList.add("dark");
- } else {
- document.documentElement.classList.remove("dark");
- }
-
- localStorage.setItem("dark_theme", JSON.stringify(value));
+ if (value) {
+ document.documentElement.style.colorScheme = "dark";
+ } else {
+ document.documentElement.style.colorScheme = "light";
}
+
+ localStorage.setItem("dark_theme", JSON.stringify(value));
},
};
}
diff --git a/src/pages/AccessibilityPage.svelte b/src/pages/AccessibilityPage.svelte
new file mode 100644
index 0000000..6b5f089
--- /dev/null
+++ b/src/pages/AccessibilityPage.svelte
@@ -0,0 +1,40 @@
+
+
+Tilgjengelighetsfunksjoner
+
+
+
+
+ Sitter du i rullestol?
+
+
+ Vi har flere busser med rullestolstøtte, med kapasitet opp til 2
+ rullestoler per buss.
+ Total kapasitet er 5 rullestilbrukere fordelt på 3 busser
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/BusPage.svelte b/src/pages/BusPage.svelte
new file mode 100644
index 0000000..ad37eca
--- /dev/null
+++ b/src/pages/BusPage.svelte
@@ -0,0 +1,81 @@
+
+
+Buss
+
+
+
+
Minibusser
+
+ Vi har idag fire minibusser, to Mercedes Sprinter og to Ford
+ Transit. Vi har også en fullelektrisk Mercedes EQV og en Mitsubishi
+ Outlander.
+ Vi finner løsninger for grupper fra 5 - 32 passasjerer med
+ støtte for inntil 3 rullestolbrukere samtidig
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Turbusser
+
+ Vi er medeier i Storfjord Turbuss AS som har tre turbusser.
+ Storfjord Turbuss AS ble etablert i 2018, og vi utfører
+ turkjøring og lager pakkeløsninger etter dine ønsker og behov.
+ Vår målsetning er å alltid være det naturlige førstevalget av
+ transportør
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/ContactPage.svelte b/src/pages/ContactPage.svelte
new file mode 100644
index 0000000..a6d6a16
--- /dev/null
+++ b/src/pages/ContactPage.svelte
@@ -0,0 +1,6 @@
+
+
+Kontakt oss
+
diff --git a/src/pages/HomePage.svelte b/src/pages/HomePage.svelte
index 2fd89ce..13652b1 100644
--- a/src/pages/HomePage.svelte
+++ b/src/pages/HomePage.svelte
@@ -1 +1,120 @@
-Home
+
+
+
+
+
+
+
+
+ Med komfort og sikkerhet i førersetet Bli med på en trygg
+ og behagelig tur
+
+
+ Minibusservice Stene AS driver personbefordring med taxi,
+ minibuss og busser.
+ Vi har lang erfaring og finner gode løsninger for kundene
+ våre.
+ Kontraktskjøring for helseforetak, busselskap og kommune
+ utgjør størsteparten av oppdragene våre, men vi tilbyr også
+ turer for privatpersoner, bedrifter og turister.
+ Vi er godkjent lærebedrift og setter kunden og miljøet i
+ fokus. Vi har både elektriske, hybride og dieselkjøretøy i
+ flåten
+
+
+
+
+
Våre tjenester
+
+
+
+
+
+
+
+
Kontakt oss
+
+
+
+
diff --git a/src/pages/TaxiPage.svelte b/src/pages/TaxiPage.svelte
new file mode 100644
index 0000000..12e8ed1
--- /dev/null
+++ b/src/pages/TaxiPage.svelte
@@ -0,0 +1,60 @@
+
+
+Taxi
+
+
+
+
Persontaxi
+
+ Vi har taxier som dekker de fleste behov.
+ Rullestoltransport, firehjulstrekk og helelektrisk bil er noen
+ av tilbudene våre.
+ Taxiene våre kan ta opp til 8 passasjerer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Pakketaxi
+
+ Vi har tilbud om pakketaxi. Både småpakker og volumkrevende gods kan
+ transporteres
+
+
+
+
+
+
+
+
+
+