Switch termine loading from static CSV to dynamic API for instant updates
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"date": "2025-10-21T13:58:04.795Z",
|
||||
"date": "2025-10-21T14:19:03.866Z",
|
||||
"preset": "node-server",
|
||||
"framework": {
|
||||
"name": "nuxt",
|
||||
|
||||
69
.output/public/_nuxt/B5GgiMm1.js
Normal file
69
.output/public/_nuxt/B5GgiMm1.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
{"id":"e3471523-9d80-4085-b77f-94b960db296e","timestamp":1761055077384}
|
||||
{"id":"8ea2eaf9-1082-435b-8f11-acd12e0664d5","timestamp":1761056336789}
|
||||
@@ -0,0 +1 @@
|
||||
{"id":"8ea2eaf9-1082-435b-8f11-acd12e0664d5","timestamp":1761056336789,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
|
||||
@@ -1 +0,0 @@
|
||||
{"id":"e3471523-9d80-4085-b77f-94b960db296e","timestamp":1761055077384,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
|
||||
1
.output/public/_nuxt/entry.BFpxHKmh.css
Normal file
1
.output/public/_nuxt/entry.BFpxHKmh.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,11 +1,2 @@
|
||||
"datum","titel","beschreibung","kategorie"
|
||||
"2025-10-25","Herbstturnier","Offenes Turnier für alle Leistungsklassen","Turnier"
|
||||
"2025-11-02","Halloween-Special","Spooky Training mit Kostümen und Süßigkeiten","Event"
|
||||
"2025-11-15","Vereinsmeisterschaft","Das Highlight der Saison - Vereinsmeisterschaft in allen Kategorien","Turnier"
|
||||
"2025-12-06","Nikolaus-Turnier","Weihnachtliches Turnier mit kleinen Geschenken","Turnier"
|
||||
"2025-12-20","Weihnachtsfeier","Gemütlicher Jahresabschluss mit Siegerehrung","Event"
|
||||
"2026-01-10","Neujahrstraining","Erstes Training im neuen Jahr","Event"
|
||||
"2026-02-14","Valentinstag-Special","Paar-Turnier für Verliebte","Turnier"
|
||||
"2026-03-15","Frühlingsturnier","Saisoneröffnung mit großem Turnier","Turnier"
|
||||
|
||||
|
||||
"2025-12-18","Weihnachtsfeier 2025 im Gasthaus Zum Einhorn in Frankfurt - Bonames","","Veranstaltung"
|
||||
|
||||
|
@@ -340,7 +340,7 @@ const client_manifest = {
|
||||
"module": true,
|
||||
"prefetch": true,
|
||||
"preload": true,
|
||||
"file": "BCCaC8ND.js",
|
||||
"file": "B5GgiMm1.js",
|
||||
"name": "entry",
|
||||
"src": "node_modules/nuxt/dist/app/entry.js",
|
||||
"isEntry": true,
|
||||
@@ -350,14 +350,14 @@ const client_manifest = {
|
||||
"node_modules/nuxt/dist/app/components/error-500.vue"
|
||||
],
|
||||
"css": [
|
||||
"entry.BiMUV0e6.css"
|
||||
"entry.BFpxHKmh.css"
|
||||
],
|
||||
"assets": [
|
||||
"Harheimer TC.CKfYAfp1.svg"
|
||||
]
|
||||
},
|
||||
"entry.BiMUV0e6.css": {
|
||||
"file": "entry.BiMUV0e6.css",
|
||||
"entry.BFpxHKmh.css": {
|
||||
"file": "entry.BFpxHKmh.css",
|
||||
"resourceType": "style",
|
||||
"prefetch": true,
|
||||
"preload": true
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import process from 'node:process';globalThis._importMeta_=globalThis._importMeta_||{url:"file:///_entry.js",env:process.env};import { defineComponent, shallowRef, h, resolveComponent, hasInjectionContext, inject, computed, getCurrentInstance, createElementBlock, provide, cloneVNode, ref, Suspense, Fragment, createApp, shallowReactive, mergeProps, unref, withCtx, createTextVNode, toRef, onErrorCaptured, onServerPrefetch, createVNode, resolveDynamicComponent, reactive, effectScope, isReadonly, isRef, isShallow, isReactive, toRaw, defineAsyncComponent, getCurrentScope, toDisplayString, useSSRContext } from 'vue';
|
||||
import process from 'node:process';globalThis._importMeta_=globalThis._importMeta_||{url:"file:///_entry.js",env:process.env};import { defineComponent, shallowRef, h, resolveComponent, hasInjectionContext, inject, computed, getCurrentInstance, createElementBlock, provide, cloneVNode, ref, Suspense, Fragment, createApp, shallowReactive, mergeProps, withCtx, createVNode, createTextVNode, unref, toDisplayString, toRef, onErrorCaptured, onServerPrefetch, resolveDynamicComponent, reactive, effectScope, isReadonly, isRef, isShallow, isReactive, toRaw, defineAsyncComponent, getCurrentScope, useSSRContext } from 'vue';
|
||||
import { p as parseQuery, c as createError$1, o as hasProtocol, q as isScriptProtocol, m as joinURL, w as withQuery, t as sanitizeStatusCode, v as withTrailingSlash, x as withoutTrailingSlash, y as getContext, $ as $fetch$1, z as createHooks, A as executeAsync, B as toRouteMatcher, C as createRouter$1, D as defu } from '../nitro/nitro.mjs';
|
||||
import { b as baseURL } from '../routes/renderer.mjs';
|
||||
import { defineStore, createPinia, setActivePinia, shouldHydrate } from 'pinia';
|
||||
import { RouterView, useRouter as useRouter$1, createMemoryHistory, createRouter, START_LOCATION, useRoute as useRoute$1 } from 'vue-router';
|
||||
import { ssrRenderAttrs, ssrInterpolate, ssrRenderComponent, ssrRenderSuspense, ssrRenderVNode, ssrRenderAttr, ssrRenderStyle, ssrRenderClass, ssrRenderList } from 'vue/server-renderer';
|
||||
import { User, ChevronUp, X, Menu, ChevronDown } from 'lucide-vue-next';
|
||||
import { RouterView, useRoute as useRoute$1, useRouter as useRouter$1, createMemoryHistory, createRouter, START_LOCATION } from 'vue-router';
|
||||
import { ssrRenderAttrs, ssrRenderComponent, ssrRenderAttr, ssrRenderStyle, ssrRenderClass, ssrRenderList, ssrInterpolate, ssrRenderSuspense, ssrRenderVNode } from 'vue/server-renderer';
|
||||
import { ChevronDown, X, Menu, User, ChevronUp } from 'lucide-vue-next';
|
||||
import 'node:http';
|
||||
import 'node:https';
|
||||
import 'node:events';
|
||||
@@ -1414,6 +1414,7 @@ const _sfc_main$4 = {
|
||||
const mobileSubmenu = ref(null);
|
||||
const mannschaften = ref([]);
|
||||
const hasGalleryImages = ref(false);
|
||||
const showCmsDropdown = ref(false);
|
||||
const isLoggedIn = computed(() => authStore.isLoggedIn);
|
||||
const isAdmin = computed(() => authStore.isAdmin);
|
||||
const currentSubmenu = computed(() => {
|
||||
@@ -1855,40 +1856,99 @@ const _sfc_main$4 = {
|
||||
_: 1
|
||||
}, _parent));
|
||||
if (isAdmin.value) {
|
||||
_push(`<!--[--><div class="h-3 w-px bg-primary-700"></div>`);
|
||||
_push(ssrRenderComponent(_component_NuxtLink, {
|
||||
to: "/cms",
|
||||
class: "px-2.5 py-1 text-xs text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded transition-all",
|
||||
"active-class": "text-white bg-primary-600"
|
||||
}, {
|
||||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||||
if (_push2) {
|
||||
_push2(` CMS `);
|
||||
} else {
|
||||
return [
|
||||
createTextVNode(" CMS ")
|
||||
];
|
||||
}
|
||||
}),
|
||||
_: 1
|
||||
}, _parent));
|
||||
_push(ssrRenderComponent(_component_NuxtLink, {
|
||||
to: "/cms/benutzer",
|
||||
class: "px-2.5 py-1 text-xs text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded transition-all",
|
||||
"active-class": "text-white bg-primary-600"
|
||||
}, {
|
||||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||||
if (_push2) {
|
||||
_push2(` Benutzerverwaltung `);
|
||||
} else {
|
||||
return [
|
||||
createTextVNode(" Benutzerverwaltung ")
|
||||
];
|
||||
}
|
||||
}),
|
||||
_: 1
|
||||
}, _parent));
|
||||
_push(`<!--]-->`);
|
||||
_push(`<!--[--><div class="h-3 w-px bg-primary-700"></div><div class="relative inline-block"><button class="${ssrRenderClass([unref(route).path.startsWith("/cms") ? "text-white bg-primary-600" : "", "px-2.5 py-1 text-xs text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded transition-all flex items-center"])}"> CMS `);
|
||||
_push(ssrRenderComponent(unref(ChevronDown), {
|
||||
size: 12,
|
||||
class: ["ml-1", ["transition-transform", showCmsDropdown.value ? "rotate-180" : ""]]
|
||||
}, null, _parent));
|
||||
_push(`</button>`);
|
||||
if (showCmsDropdown.value) {
|
||||
_push(`<div class="absolute left-0 top-full mt-1 w-48 bg-gray-800 border border-gray-700 rounded-lg shadow-xl overflow-hidden z-50">`);
|
||||
_push(ssrRenderComponent(_component_NuxtLink, {
|
||||
to: "/cms",
|
||||
onClick: ($event) => showCmsDropdown.value = false,
|
||||
class: "block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
||||
}, {
|
||||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||||
if (_push2) {
|
||||
_push2(` Übersicht `);
|
||||
} else {
|
||||
return [
|
||||
createTextVNode(" Übersicht ")
|
||||
];
|
||||
}
|
||||
}),
|
||||
_: 1
|
||||
}, _parent));
|
||||
_push(ssrRenderComponent(_component_NuxtLink, {
|
||||
to: "/mitgliederbereich/news",
|
||||
onClick: ($event) => showCmsDropdown.value = false,
|
||||
class: "block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
||||
}, {
|
||||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||||
if (_push2) {
|
||||
_push2(` Interne News `);
|
||||
} else {
|
||||
return [
|
||||
createTextVNode(" Interne News ")
|
||||
];
|
||||
}
|
||||
}),
|
||||
_: 1
|
||||
}, _parent));
|
||||
_push(ssrRenderComponent(_component_NuxtLink, {
|
||||
to: "/cms/termine",
|
||||
onClick: ($event) => showCmsDropdown.value = false,
|
||||
class: "block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
||||
}, {
|
||||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||||
if (_push2) {
|
||||
_push2(` Termine `);
|
||||
} else {
|
||||
return [
|
||||
createTextVNode(" Termine ")
|
||||
];
|
||||
}
|
||||
}),
|
||||
_: 1
|
||||
}, _parent));
|
||||
_push(ssrRenderComponent(_component_NuxtLink, {
|
||||
to: "/mitgliederbereich/mitglieder",
|
||||
onClick: ($event) => showCmsDropdown.value = false,
|
||||
class: "block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
||||
}, {
|
||||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||||
if (_push2) {
|
||||
_push2(` Mitglieder `);
|
||||
} else {
|
||||
return [
|
||||
createTextVNode(" Mitglieder ")
|
||||
];
|
||||
}
|
||||
}),
|
||||
_: 1
|
||||
}, _parent));
|
||||
_push(ssrRenderComponent(_component_NuxtLink, {
|
||||
to: "/cms/benutzer",
|
||||
onClick: ($event) => showCmsDropdown.value = false,
|
||||
class: "block px-4 py-2 text-sm text-gray-300 hover:bg-primary-600 hover:text-white transition-colors"
|
||||
}, {
|
||||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||||
if (_push2) {
|
||||
_push2(` Benutzerverwaltung `);
|
||||
} else {
|
||||
return [
|
||||
createTextVNode(" Benutzerverwaltung ")
|
||||
];
|
||||
}
|
||||
}),
|
||||
_: 1
|
||||
}, _parent));
|
||||
_push(`</div>`);
|
||||
} else {
|
||||
_push(`<!---->`);
|
||||
}
|
||||
_push(`</div><!--]-->`);
|
||||
} else {
|
||||
_push(`<!---->`);
|
||||
}
|
||||
@@ -2310,14 +2370,62 @@ const _sfc_main$4 = {
|
||||
_push(ssrRenderComponent(_component_NuxtLink, {
|
||||
to: "/cms",
|
||||
onClick: ($event) => isMobileMenuOpen.value = false,
|
||||
class: "block px-4 py-2 text-sm font-semibold text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
||||
}, {
|
||||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||||
if (_push2) {
|
||||
_push2(` CMS Übersicht `);
|
||||
} else {
|
||||
return [
|
||||
createTextVNode(" CMS Übersicht ")
|
||||
];
|
||||
}
|
||||
}),
|
||||
_: 1
|
||||
}, _parent));
|
||||
_push(ssrRenderComponent(_component_NuxtLink, {
|
||||
to: "/mitgliederbereich/news",
|
||||
onClick: ($event) => isMobileMenuOpen.value = false,
|
||||
class: "block px-4 py-2 text-sm text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
||||
}, {
|
||||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||||
if (_push2) {
|
||||
_push2(` CMS `);
|
||||
_push2(` Interne News `);
|
||||
} else {
|
||||
return [
|
||||
createTextVNode(" CMS ")
|
||||
createTextVNode(" Interne News ")
|
||||
];
|
||||
}
|
||||
}),
|
||||
_: 1
|
||||
}, _parent));
|
||||
_push(ssrRenderComponent(_component_NuxtLink, {
|
||||
to: "/cms/termine",
|
||||
onClick: ($event) => isMobileMenuOpen.value = false,
|
||||
class: "block px-4 py-2 text-sm text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
||||
}, {
|
||||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||||
if (_push2) {
|
||||
_push2(` Termine `);
|
||||
} else {
|
||||
return [
|
||||
createTextVNode(" Termine ")
|
||||
];
|
||||
}
|
||||
}),
|
||||
_: 1
|
||||
}, _parent));
|
||||
_push(ssrRenderComponent(_component_NuxtLink, {
|
||||
to: "/mitgliederbereich/mitglieder",
|
||||
onClick: ($event) => isMobileMenuOpen.value = false,
|
||||
class: "block px-4 py-2 text-sm text-yellow-300 hover:text-white hover:bg-primary-700/50 rounded-lg transition-colors"
|
||||
}, {
|
||||
default: withCtx((_, _push2, _parent2, _scopeId) => {
|
||||
if (_push2) {
|
||||
_push2(` Mitglieder `);
|
||||
} else {
|
||||
return [
|
||||
createTextVNode(" Mitglieder ")
|
||||
];
|
||||
}
|
||||
}),
|
||||
@@ -2381,6 +2489,7 @@ _sfc_main$4.setup = (props, ctx) => {
|
||||
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("components/Navigation.vue");
|
||||
return _sfc_setup$4 ? _sfc_setup$4(props, ctx) : void 0;
|
||||
};
|
||||
const Navigation = Object.assign(_sfc_main$4, { __name: "Navigation" });
|
||||
const _sfc_main$3 = {
|
||||
__name: "Footer",
|
||||
__ssrInlineRender: true,
|
||||
@@ -2511,7 +2620,7 @@ const _sfc_main$2 = {
|
||||
return (_ctx, _push, _parent, _attrs) => {
|
||||
const _component_NuxtPage = __nuxt_component_0;
|
||||
_push(`<div${ssrRenderAttrs(mergeProps({ class: "h-screen flex flex-col overflow-hidden" }, _attrs))}>`);
|
||||
_push(ssrRenderComponent(_sfc_main$4, null, null, _parent));
|
||||
_push(ssrRenderComponent(Navigation, null, null, _parent));
|
||||
_push(`<main class="flex-1 overflow-y-auto pt-20">`);
|
||||
_push(ssrRenderComponent(_component_NuxtPage, null, null, _parent));
|
||||
_push(`</main>`);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -272,7 +272,7 @@ async function renderInlineStyles(usedModules) {
|
||||
|
||||
const renderSSRHeadOptions = {"omitLineBreaks":true};
|
||||
|
||||
const entryFileName = "BCCaC8ND.js";
|
||||
const entryFileName = "B5GgiMm1.js";
|
||||
|
||||
globalThis.__buildAssetsURL = buildAssetsURL;
|
||||
globalThis.__publicAssetsURL = publicAssetsURL;
|
||||
|
||||
@@ -87,50 +87,11 @@ const formatMonth = (dateString) => {
|
||||
|
||||
const loadTermine = async () => {
|
||||
try {
|
||||
console.log('Lade Termine...')
|
||||
const response = await fetch('/data/termine.csv')
|
||||
console.log('Response:', response)
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
|
||||
const csv = await response.text()
|
||||
console.log('CSV Text:', csv)
|
||||
|
||||
// Vereinfachter CSV-Parser
|
||||
const lines = csv.split('\n').filter(line => line.trim() !== '')
|
||||
console.log('CSV Lines:', lines)
|
||||
|
||||
if (lines.length < 2) {
|
||||
console.log('Keine Datenzeilen gefunden')
|
||||
return
|
||||
}
|
||||
|
||||
termine.value = lines.slice(1).map((line, index) => {
|
||||
// Entferne Anführungszeichen und teile bei Kommas
|
||||
const cleanLine = line.replace(/"/g, '')
|
||||
const values = cleanLine.split(',')
|
||||
|
||||
if (values.length < 4) {
|
||||
console.log(`Zeile ${index + 2} hat zu wenige Werte:`, values)
|
||||
return null
|
||||
}
|
||||
|
||||
const termin = {
|
||||
datum: values[0].trim(),
|
||||
titel: values[1].trim(),
|
||||
beschreibung: values[2].trim(),
|
||||
kategorie: values[3].trim()
|
||||
}
|
||||
|
||||
console.log(`Termin ${index + 1}:`, termin)
|
||||
return termin
|
||||
}).filter(termin => termin !== null)
|
||||
|
||||
console.log('Alle geparsten Termine:', termine.value)
|
||||
const response = await $fetch('/api/termine')
|
||||
termine.value = response.termine || []
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Termine:', error)
|
||||
termine.value = []
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,51 +101,11 @@ const formatFullDate = (dateString) => {
|
||||
|
||||
const loadTermine = async () => {
|
||||
try {
|
||||
const response = await fetch('/data/termine.csv')
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
|
||||
const csv = await response.text()
|
||||
const lines = csv.split('\n').filter(line => line.trim() !== '')
|
||||
|
||||
if (lines.length < 2) {
|
||||
return
|
||||
}
|
||||
|
||||
termine.value = lines.slice(1).map((line, index) => {
|
||||
// Besserer CSV-Parser: Respektiert Anführungszeichen
|
||||
const values = []
|
||||
let current = ''
|
||||
let inQuotes = false
|
||||
|
||||
for (let i = 0; i < line.length; i++) {
|
||||
const char = line[i]
|
||||
|
||||
if (char === '"') {
|
||||
inQuotes = !inQuotes
|
||||
} else if (char === ',' && !inQuotes) {
|
||||
values.push(current.trim())
|
||||
current = ''
|
||||
} else {
|
||||
current += char
|
||||
}
|
||||
}
|
||||
values.push(current.trim())
|
||||
|
||||
if (values.length < 4) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
datum: values[0].trim(),
|
||||
titel: values[1].trim(),
|
||||
beschreibung: values[2].trim(),
|
||||
kategorie: values[3].trim()
|
||||
}
|
||||
}).filter(termin => termin !== null)
|
||||
const response = await $fetch('/api/termine')
|
||||
termine.value = response.termine || []
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Termine:', error)
|
||||
termine.value = []
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,2 @@
|
||||
"datum","titel","beschreibung","kategorie"
|
||||
"2025-10-25","Herbstturnier","Offenes Turnier für alle Leistungsklassen","Turnier"
|
||||
"2025-11-02","Halloween-Special","Spooky Training mit Kostümen und Süßigkeiten","Event"
|
||||
"2025-11-15","Vereinsmeisterschaft","Das Highlight der Saison - Vereinsmeisterschaft in allen Kategorien","Turnier"
|
||||
"2025-12-06","Nikolaus-Turnier","Weihnachtliches Turnier mit kleinen Geschenken","Turnier"
|
||||
"2025-12-20","Weihnachtsfeier","Gemütlicher Jahresabschluss mit Siegerehrung","Event"
|
||||
"2026-01-10","Neujahrstraining","Erstes Training im neuen Jahr","Event"
|
||||
"2026-02-14","Valentinstag-Special","Paar-Turnier für Verliebte","Turnier"
|
||||
"2026-03-15","Frühlingsturnier","Saisoneröffnung mit großem Turnier","Turnier"
|
||||
|
||||
|
||||
"2025-12-18","Weihnachtsfeier 2025 im Gasthaus Zum Einhorn in Frankfurt - Bonames","","Veranstaltung"
|
||||
|
||||
|
62
server/api/termine.get.js
Normal file
62
server/api/termine.get.js
Normal file
@@ -0,0 +1,62 @@
|
||||
import { promises as fs } from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
try {
|
||||
const cwd = process.cwd()
|
||||
|
||||
// In production (.output/server), working dir is .output
|
||||
let csvPath
|
||||
if (cwd.endsWith('.output')) {
|
||||
csvPath = path.join(cwd, '../public/data/termine.csv')
|
||||
} else {
|
||||
csvPath = path.join(cwd, 'public/data/termine.csv')
|
||||
}
|
||||
|
||||
const csv = await fs.readFile(csvPath, 'utf-8')
|
||||
const lines = csv.split('\n').filter(line => line.trim() !== '')
|
||||
|
||||
if (lines.length < 2) {
|
||||
return { success: true, termine: [] }
|
||||
}
|
||||
|
||||
const termine = []
|
||||
for (let i = 1; i < lines.length; i++) {
|
||||
const values = []
|
||||
let current = ''
|
||||
let inQuotes = false
|
||||
|
||||
for (let j = 0; j < lines[i].length; j++) {
|
||||
const char = lines[i][j]
|
||||
|
||||
if (char === '"') {
|
||||
inQuotes = !inQuotes
|
||||
} else if (char === ',' && !inQuotes) {
|
||||
values.push(current.trim())
|
||||
current = ''
|
||||
} else {
|
||||
current += char
|
||||
}
|
||||
}
|
||||
values.push(current.trim())
|
||||
|
||||
if (values.length >= 4) {
|
||||
termine.push({
|
||||
datum: values[0],
|
||||
titel: values[1],
|
||||
beschreibung: values[2],
|
||||
kategorie: values[3]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
termine
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Laden der Termine:', error)
|
||||
return { success: true, termine: [] }
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user