Просмотр исходного кода

added calendar event ics file creator

liontix 1 год назад
Родитель
Сommit
5d3a6e9e9a

+ 2 - 1
package.json

@@ -4,7 +4,7 @@
 	"version": "0.0.1",
 	"type": "module",
 	"scripts": {
-		"dev": "vite dev",
+		"dev": "vite dev --host",
 		"build": "vite build",
 		"preview": "vite preview",
 		"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
@@ -33,6 +33,7 @@
 	"dependencies": {
 		"@sveltejs/adapter-vercel": "^5.5.2",
 		"beercss": "^3.8.0",
+		"ics": "^3.8.1",
 		"moment": "^2.30.1",
 		"validator": "^13.12.0"
 	}

+ 4 - 0
src/lib/funcs.ts

@@ -34,6 +34,10 @@ export function getTimeSlots(startDate: string, startTime: string, endTime: stri
     return timeSlots;
 }
 
+export function toLocalDTSTAMP(date: moment.Moment): string {
+    return date.format("YYYYMMDDTHHmmss") + "Z";
+}
+
 export function isDueDatePassed(dueDate: Date) {
     return moment(dueDate).isBefore();
 }

+ 1 - 1
src/lib/index.ts

@@ -2,7 +2,7 @@ import { writable, type Writable } from "svelte/store";
 import { browser } from "$app/environment";
 
 // place files you want to import through the `$lib` alias in this folder.
-export const api_host = "http://localhost:3000";
+export const api_host = "http://192.168.178.82:3000";
  //export let authToken: string = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY3OTIxYTcyMTNiM2NkYjc5NGZmNzQ2MiIsImlhdCI6MTczNzcyOTYwMiwiZXhwIjoxNzM3NzUxMjAyfQ.-TlU0izsSJnZYE79yG01fcRgzgBirZBJBsiQf2alwZ4";
 
 export let authToken: Writable<string>;

+ 72 - 23
src/lib/modules/AppointmentConfirmDialog.svelte

@@ -1,38 +1,87 @@
 <script lang="ts">
-	import type { Appointment, AppointmentInputs, DynamicJson } from "$lib/dbdata";
-	import { extractTime } from "$lib/funcs";
-	import AppointmentInfo from "./AppointmentInfo.svelte";
-	import AppointmentRegisterInputs from "./AppointmentRegisterInputs.svelte";
+	import type { Appointment, AppointmentInputs, DynamicJson } from '$lib/dbdata';
+	import { extractTime, toLocalDTSTAMP } from '$lib/funcs';
+	import moment from 'moment';
+	import AppointmentInfo from './AppointmentInfo.svelte';
+	import AppointmentRegisterInputs from './AppointmentRegisterInputs.svelte';
+	import { createEvent } from 'ics';
 
-  export let active: boolean;
+	export let active: boolean;
 
-  export let appointment: Appointment;
-  export let date: Date = new Date();
-  export let dynamicInputs: DynamicJson[] = [];
+	export let appointment: Appointment;
+	export let date: Date = new Date();
+	export let dynamicInputs: DynamicJson[] = [];
 
-  let errorMessage: string = "";
-  let successMessage: string = "";
+	let errorMessage: string = '';
+	let successMessage: string = '';
+	let enableICSDownload: boolean = false;
 
-  let time: string = "00:00";
+	let time: string = '00:00';
 
-  $: {
-    time = extractTime(date);
-  }
+	function createEventICS() {
+    const formattedDate: string = toLocalDTSTAMP(moment.utc(date.toLocaleString()));
+    console.log(formattedDate);
+
+		createEvent(
+			{
+				title: appointment.title,
+				description: appointment.description,
+				busyStatus: 'BUSY',
+        start: formattedDate,
+				duration: { minutes: appointment.duration }
+			},
+			(error, value) => {
+				if (error) {
+					console.log(error);
+				}
+				const blob = new Blob([value], { type: 'text/calendar' });
+        const url = window.URL.createObjectURL(blob);
+
+        setTimeout(() => {
+            window.location.href = url; // Triggers opening on supported devices
+        }, 1000);
+			}
+		);
+	}
+
+	$: {
+		time = extractTime(date);
+	}
 </script>
 
-<dialog class="max {active ? 'active': ''}">
-    <div class="center medium-padding">
-      <AppointmentInfo bind:title={appointment.title} bind:location={appointment.place} bind:description={appointment.description}
-          bind:time bind:date isConfirmation={true} />
+<dialog class="max {active ? 'active' : ''}">
+	<div class="center medium-padding">
+		<AppointmentInfo
+			bind:title={appointment.title}
+			bind:location={appointment.place}
+			bind:description={appointment.description}
+			bind:time
+			bind:date
+			isConfirmation={true}
+		/>
+
+		<AppointmentRegisterInputs
+			bind:modalActive={active}
+      bind:booked={enableICSDownload}
+			bind:errorMessage
+			bind:successMessage
+			bind:date
+			bind:appointmentId={appointment._id}
+			bind:dynamicInputs
+		/>
+	</div>
 
-      <AppointmentRegisterInputs bind:modalActive={active} bind:errorMessage bind:successMessage bind:date bind:appointmentId={appointment._id} bind:dynamicInputs />
-  </div>
+  {#if enableICSDownload && false}
+    <button class="responsive green" on:click={createEventICS}>Download ICS</button>
+  {/if}
 </dialog>
-  
+
+
 {#if errorMessage}
-    <div class="snackbar error active">{errorMessage}</div>
+	<div class="snackbar error active">{errorMessage}</div>
 {/if}
 
+
 {#if successMessage}
-    <div class="snackbar green active">{successMessage}</div>
+	<div class="snackbar green active">{successMessage}</div>
 {/if}

+ 2 - 0
src/lib/modules/AppointmentRegisterInputs.svelte

@@ -7,6 +7,7 @@
     export let appointmentId: string;
     export let date: Date;
     export let modalActive: boolean;
+    export let booked: boolean = false;
 
     export let errorMessage: string = "";
     export let successMessage: string = "";
@@ -46,6 +47,7 @@
             if (response.status === 200) {
                 errorMessage = "";
                 successMessage = "successfully booked";
+                booked = true;
             } else {
                 successMessage = "";
                 errorMessage = "invalid booking";

+ 3 - 3
src/lib/modules/EventTables.svelte

@@ -102,10 +102,10 @@
 {#each appointmentData as data}
 	<tr>
 		<td>{data.title}</td>
-		<td on:click={() => copyShareLink(data._id)} class="center-align">
-			<button class="medium cyan">
+		<td  class="center-align">
+			<a href={`/appointment?id=${data._id}`} class="button medium cyan">
 				<span>Teilen</span>
-			</button>
+			</a>
 		</td>
         {#if !isDueDatePassed(data.dueDate)}          
             <td on:click={() => lockAppointment(data._id)} class="center-align">