penambahan route protection
This commit is contained in:
@@ -258,6 +258,7 @@
|
|||||||
console.error("Logout failed:", error.message);
|
console.error("Logout failed:", error.message);
|
||||||
} else {
|
} else {
|
||||||
localStorage.removeItem("user");
|
localStorage.removeItem("user");
|
||||||
|
|
||||||
goto("/login");
|
goto("/login");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { redirect } from '@sveltejs/kit';
|
// import { redirect } from '@sveltejs/kit';
|
||||||
import type { LayoutServerLoad } from './$types';
|
// import type { LayoutServerLoad } from './$types';
|
||||||
|
|
||||||
export const load: LayoutServerLoad = async ({ locals }) => {
|
// export const load: LayoutServerLoad = async ({ locals }) => {
|
||||||
if (!locals.user) {
|
// if (!locals.user) {
|
||||||
throw redirect(303, '/login');
|
// throw redirect(303, '/login');
|
||||||
}
|
// }
|
||||||
|
|
||||||
return {
|
// return {
|
||||||
user: locals.user
|
// user: locals.user
|
||||||
};
|
// };
|
||||||
};
|
// };
|
||||||
@@ -1,13 +1,44 @@
|
|||||||
<script>
|
<script lang="ts">
|
||||||
|
import { writable } from "svelte/store";
|
||||||
import Sidebar from "../../components/Sidebar.svelte";
|
import Sidebar from "../../components/Sidebar.svelte";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { supabase } from "$lib/supabaseClient";
|
||||||
|
import { goto } from "$app/navigation";
|
||||||
|
import type { Session } from "@supabase/supabase-js";
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
|
|
||||||
let notifications = 3; // Contoh jumlah notifikasi
|
let notifications = 3;
|
||||||
let user = {
|
let user = {
|
||||||
name: "John Doe",
|
name: "John Doe",
|
||||||
avatar: "https://i.pravatar.cc/40", // Avatar placeholder
|
avatar: "https://i.pravatar.cc/40",
|
||||||
};
|
};
|
||||||
|
let userdata: any = null;
|
||||||
|
|
||||||
|
const session = writable<Session | null>(null);
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
const {
|
||||||
|
data: { session: currentSession },
|
||||||
|
} = await supabase.auth.getSession();
|
||||||
|
|
||||||
|
session.set(currentSession || null);
|
||||||
|
|
||||||
|
supabase.auth.onAuthStateChange((event, sessionValue) => {
|
||||||
|
session.set(sessionValue);
|
||||||
|
if (!sessionValue) goto("/login");
|
||||||
|
});
|
||||||
|
|
||||||
|
const userStr = localStorage.getItem("user");
|
||||||
|
if (userStr) {
|
||||||
|
userdata = JSON.parse(userStr);
|
||||||
|
} else {
|
||||||
|
goto("/login");
|
||||||
|
}
|
||||||
|
|
||||||
|
user.name = userdata.full_name || "Guest";
|
||||||
|
user.avatar = userdata.profile_picture || "https://i.pravatar.cc/40";
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex h-screen">
|
<div class="flex h-screen">
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
import { supabase } from "$lib/supabaseClient";
|
||||||
import { redirect } from "@sveltejs/kit";
|
import { redirect } from "@sveltejs/kit";
|
||||||
|
|
||||||
export const load = async (event) => {
|
import type { RequestEvent } from "@sveltejs/kit";
|
||||||
if (!event.locals.user){
|
|
||||||
|
export const load = async (event: RequestEvent & { locals: { user?: any } }) => {
|
||||||
|
|
||||||
|
if (!event.locals.user) {
|
||||||
console.log(event.url)
|
console.log(event.url)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -90,7 +90,6 @@
|
|||||||
{ label: "Guest", value: "Guest" },
|
{ label: "Guest", value: "Guest" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
let currentUserId: string | null = null;
|
let currentUserId: string | null = null;
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
@@ -226,8 +225,6 @@
|
|||||||
: issue.approval
|
: issue.approval
|
||||||
? "APPROVED"
|
? "APPROVED"
|
||||||
: "REJECTED", // or map as needed
|
: "REJECTED", // or map as needed
|
||||||
approved_by: issue.approved_by ?? null,
|
|
||||||
approved_date: issue.approved_date ? new Date(issue.approved_date) : null,
|
|
||||||
total_hours_work:
|
total_hours_work:
|
||||||
Math.abs(
|
Math.abs(
|
||||||
new Date(issue.datetime_out).getTime() -
|
new Date(issue.datetime_out).getTime() -
|
||||||
@@ -395,8 +392,8 @@
|
|||||||
const approved_date = new Date().toISOString();
|
const approved_date = new Date().toISOString();
|
||||||
const { error } = await supabase
|
const { error } = await supabase
|
||||||
.from("vb_timesheet")
|
.from("vb_timesheet")
|
||||||
.update({
|
.update({
|
||||||
approval: status ,
|
approval: status,
|
||||||
approved_by,
|
approved_by,
|
||||||
approved_date,
|
approved_date,
|
||||||
})
|
})
|
||||||
@@ -721,7 +718,9 @@
|
|||||||
>Select Villa</option
|
>Select Villa</option
|
||||||
>
|
>
|
||||||
{#each dataVilla as villa}
|
{#each dataVilla as villa}
|
||||||
<option value={villa.id}>{villa.villa_name}</option>
|
<option value={villa.id}
|
||||||
|
>{villa.villa_name}</option
|
||||||
|
>
|
||||||
{/each}
|
{/each}
|
||||||
</select>
|
</select>
|
||||||
{#if $formErrors[col.key]}
|
{#if $formErrors[col.key]}
|
||||||
|
|||||||
@@ -1,49 +1,73 @@
|
|||||||
<script>
|
<script>
|
||||||
import { supabase } from '$lib/supabaseClient';
|
import { supabase } from "$lib/supabaseClient";
|
||||||
import StarRating from '$lib/StarRating.svelte';
|
import StarRating from "$lib/StarRating.svelte";
|
||||||
import villaBugisImage from '$lib/images/villa-bugis.png';
|
import villaBugisImage from "$lib/images/villa-bugis.png";
|
||||||
|
|
||||||
|
|
||||||
const WEBHOOK_URL = 'https://flow.catalis.app/webhook/vb_feedback_new';
|
const WEBHOOK_URL = "https://flow.catalis.app/webhook/vb_feedback_new";
|
||||||
|
|
||||||
let villa_name = '';
|
let villa_name = "";
|
||||||
let customer_name = '';
|
let customer_name = "";
|
||||||
let checkin_date = '';
|
let checkin_date = "";
|
||||||
let checkout_date = '';
|
let checkout_date = "";
|
||||||
let feedback = '';
|
let feedback = "";
|
||||||
let errorMessage = '';
|
let errorMessage = "";
|
||||||
let book_process = '';
|
let book_process = "";
|
||||||
let airport_greet = '';
|
let airport_greet = "";
|
||||||
let arrival_greet = '';
|
let arrival_greet = "";
|
||||||
let maintenance_proc = '';
|
let maintenance_proc = "";
|
||||||
let bf_service = '';
|
let bf_service = "";
|
||||||
|
|
||||||
// Star ratings (1-5)
|
// Star ratings (1-5)
|
||||||
let overal_star = 0;
|
let overal_star = 0;
|
||||||
|
|
||||||
// Boolean checkboxes
|
// Boolean checkboxes
|
||||||
let extend_disc = false;
|
let extend_disc = false;
|
||||||
let nextstay_disc = false;
|
let nextstay_disc = false;
|
||||||
let become_sponsor = false;
|
let become_sponsor = false;
|
||||||
|
|
||||||
async function handleSubmit() {
|
async function handleSubmit() {
|
||||||
errorMessage = '';
|
errorMessage = "";
|
||||||
|
|
||||||
if (!villa_name.trim() || !customer_name.trim() || !feedback.trim()) {
|
if (!villa_name.trim() || !customer_name.trim() || !feedback.trim()) {
|
||||||
errorMessage = 'Villa, Name, and feedback are required.';
|
errorMessage = "Villa, Name, and feedback are required.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new Date(checkout_date) <= new Date(checkin_date)) {
|
if (new Date(checkout_date) <= new Date(checkin_date)) {
|
||||||
errorMessage = 'Check-out date must be after check-in date.';
|
errorMessage = "Check-out date must be after check-in date.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = (await supabase.auth.getUser()).data.user;
|
const user = (await supabase.auth.getUser()).data.user;
|
||||||
|
|
||||||
const { data, error } = await supabase
|
const { data, error } = await supabase.from("vb_feedback").insert([
|
||||||
.from('vb_feedback')
|
{
|
||||||
.insert([{
|
villa_name,
|
||||||
|
customer_name,
|
||||||
|
checkin_date,
|
||||||
|
checkout_date,
|
||||||
|
feedback,
|
||||||
|
book_process,
|
||||||
|
airport_greet,
|
||||||
|
arrival_greet,
|
||||||
|
bf_service,
|
||||||
|
overal_star,
|
||||||
|
maintenance_proc,
|
||||||
|
extend_disc,
|
||||||
|
nextstay_disc,
|
||||||
|
become_sponsor,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("Error submitting feedback:", error.message);
|
||||||
|
errorMessage = "Failed to submit feedback. Please try again.";
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
await fetch(WEBHOOK_URL, {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({
|
||||||
villa_name,
|
villa_name,
|
||||||
customer_name,
|
customer_name,
|
||||||
checkin_date,
|
checkin_date,
|
||||||
@@ -52,167 +76,233 @@
|
|||||||
book_process,
|
book_process,
|
||||||
airport_greet,
|
airport_greet,
|
||||||
arrival_greet,
|
arrival_greet,
|
||||||
|
maintenance_proc,
|
||||||
bf_service,
|
bf_service,
|
||||||
overal_star,
|
overal_star,
|
||||||
maintenance_proc,
|
|
||||||
extend_disc,
|
extend_disc,
|
||||||
nextstay_disc,
|
nextstay_disc,
|
||||||
become_sponsor
|
become_sponsor,
|
||||||
}]);
|
}),
|
||||||
|
});
|
||||||
|
} catch (webhookError) {
|
||||||
|
console.error("Webhook failed:", webhookError);
|
||||||
|
}
|
||||||
|
|
||||||
if (error) {
|
// Reset form
|
||||||
console.error('Error submitting feedback:', error.message);
|
villa_name = "";
|
||||||
errorMessage = 'Failed to submit feedback. Please try again.';
|
customer_name = "";
|
||||||
} else {
|
checkin_date = "";
|
||||||
try {
|
checkout_date = "";
|
||||||
await fetch(WEBHOOK_URL, {
|
feedback = "";
|
||||||
method: 'POST',
|
book_process = "";
|
||||||
headers: { 'Content-Type': 'application/json' },
|
airport_greet = "";
|
||||||
body: JSON.stringify({
|
arrival_greet = "";
|
||||||
villa_name,
|
maintenance_proc = "";
|
||||||
customer_name,
|
bf_service = "";
|
||||||
checkin_date,
|
overal_star = 0;
|
||||||
checkout_date,
|
extend_disc = false;
|
||||||
feedback,
|
nextstay_disc = false;
|
||||||
book_process,
|
become_sponsor = false;
|
||||||
airport_greet,
|
|
||||||
arrival_greet,
|
|
||||||
maintenance_proc,
|
|
||||||
bf_service,
|
|
||||||
overal_star,
|
|
||||||
extend_disc,
|
|
||||||
nextstay_disc,
|
|
||||||
become_sponsor
|
|
||||||
})
|
|
||||||
});
|
|
||||||
} catch (webhookError) {
|
|
||||||
console.error('Webhook failed:', webhookError);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset form
|
alert("Feedback submitted successfully!");
|
||||||
villa_name = '';
|
|
||||||
customer_name = '';
|
|
||||||
checkin_date = '';
|
|
||||||
checkout_date = '';
|
|
||||||
feedback = '';
|
|
||||||
book_process = '';
|
|
||||||
airport_greet = '';
|
|
||||||
arrival_greet = '';
|
|
||||||
maintenance_proc = '';
|
|
||||||
bf_service = '';
|
|
||||||
overal_star = 0;
|
|
||||||
extend_disc = false;
|
|
||||||
nextstay_disc = false;
|
|
||||||
become_sponsor = false;
|
|
||||||
|
|
||||||
alert("Feedback submitted successfully!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
}
|
||||||
|
</script>
|
||||||
<div class="max-w-xl mx-auto px-4">
|
|
||||||
<div class="flex justify-between items-center p-4">
|
<div class="max-w-xl mx-auto px-4">
|
||||||
<div class="w-1/3 flex justify-start">
|
<div class="flex justify-between items-center p-4">
|
||||||
<img
|
<div class="w-1/3 flex justify-start">
|
||||||
src="https://api.qrserver.com/v1/create-qr-code/?data=https%3A%2F%2Fvillabugis.com&size=200x200"
|
<img
|
||||||
alt="Villa Bugis QR Code"
|
src="https://api.qrserver.com/v1/create-qr-code/?data=https%3A%2F%2Fvillabugis.com&size=200x200"
|
||||||
class="h-24 w-24 object-contain"
|
alt="Villa Bugis QR Code"
|
||||||
/>
|
class="h-24 w-24 object-contain"
|
||||||
</div>
|
/>
|
||||||
<div class="w-1/3 text-center">
|
</div>
|
||||||
<h1 class="text-3xl font-bold text-green-800 leading-snug">
|
<div class="w-1/3 text-center">
|
||||||
Guest<br />Feedback<br />Form
|
<h1 class="text-3xl font-bold text-green-800 leading-snug">
|
||||||
</h1>
|
Guest<br />Feedback<br />Form
|
||||||
</div>
|
</h1>
|
||||||
<div class="w-1/3 flex justify-end">
|
</div>
|
||||||
<img src={villaBugisImage} alt="Villa Bugis Logo" class="h-24 w-auto" />
|
<div class="w-1/3 flex justify-end">
|
||||||
</div>
|
<img src={villaBugisImage} alt="Villa Bugis Logo" class="h-24 w-auto" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<form on:submit|preventDefault={handleSubmit} class="flex flex-col gap-4 max-w-xl mx-auto p-6 bg-white rounded-xl shadow-md">
|
|
||||||
|
|
||||||
{#if errorMessage}
|
|
||||||
<div class="text-red-600 font-semibold">{errorMessage}</div>
|
|
||||||
{/if}
|
|
||||||
<label for="fb_villaname" class="flex flex-col">Villa Name</label>
|
|
||||||
<input id="fb_villaname" type="text" bind:value={villa_name} placeholder="Villa Name" required class="p-2 border rounded-md" />
|
|
||||||
<label for="fb_gn" class="flex flex-col">Name</label>
|
|
||||||
<input id="fb_gn" type="text" bind:value={customer_name} placeholder="Customer Name" required class="p-2 border rounded-md" />
|
|
||||||
<label for="fb_cid" class="flex flex-col">Checkin Date</label>
|
|
||||||
<input id="fb_cid" type="date" bind:value={checkin_date} required class="p-2 border rounded-md" />
|
|
||||||
<label for="fb_cod" class="flex flex-col">Checkout Date</label>
|
|
||||||
<input id="fb_cod" type="date" bind:value={checkout_date} required class="p-2 border rounded-md" />
|
|
||||||
<!-- Star Ratings -->
|
|
||||||
<label class="flex flex-col">
|
|
||||||
Booking Process:
|
|
||||||
<small class="text-sm text-gray-500 mb-1">Please highlights of the booking process (anything neglected by the staff or something done well by the staff)</small>
|
|
||||||
<textarea bind:value={book_process} placeholder="Write your feedback here..." required class="p-2 border rounded-md min-h-[120px]"></textarea>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label class="flex flex-col">
|
|
||||||
Airport Greeting and Transportation:
|
|
||||||
<small class="text-sm text-gray-500 mb-1">Please highlights of the airport transfer experience (anything neglected by the staff or something done well by the staff)</small>
|
|
||||||
<textarea bind:value={airport_greet} placeholder="Write your feedback here..." required class="p-2 border rounded-md min-h-[120px]"></textarea>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label class="flex flex-col">
|
|
||||||
Arrival & Check-in:
|
|
||||||
<small class="text-sm text-gray-500 mb-1">Please highlights of the arrival and check-in process(anything neglected by the staff or something done well by the staff)</small>
|
|
||||||
<textarea bind:value={arrival_greet} placeholder="Write your feedback here..." required class="p-2 border rounded-md min-h-[120px]"></textarea>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label class="flex flex-col">
|
|
||||||
Breakfast Service or other food and beverage service utilized:
|
|
||||||
<small class="text-sm text-gray-500 mb-1">Please highlighs of the breakfast service(anything neglected by the staff or something done well by the staff)</small>
|
|
||||||
<textarea bind:value={bf_service} placeholder="Write your feedback here..." required class="p-2 border rounded-md min-h-[120px]"></textarea>
|
|
||||||
</label>
|
|
||||||
<label class="flex flex-col">
|
|
||||||
Housekeeping and Maintenance:
|
|
||||||
<small class="text-sm text-gray-500 mb-1">Please highlighs of the housekeeping and maintenance service(anything neglected by the staff or something done well by the staff)</small>
|
|
||||||
<textarea bind:value={maintenance_proc} placeholder="Write your feedback here..." required class="p-2 border rounded-md min-h-[120px]"></textarea>
|
|
||||||
</label>
|
|
||||||
<label class="flex flex-col">
|
|
||||||
What did you think of the villa in General:
|
|
||||||
<small class="text-sm text-gray-500 mb-1">Did you have any other issue of area you would like to highligh during stay? Please let us know any other comments you have - the good, the bad, and the ugly</small>
|
|
||||||
<textarea bind:value={feedback} placeholder="Write your feedback here..." required class="p-2 border rounded-md min-h-[120px]"></textarea>
|
|
||||||
</label>
|
|
||||||
<!-- Centered big star-->
|
|
||||||
<div class="text-center mt-6">
|
|
||||||
<small class="text-sm text-gray-500 block mb-2">
|
|
||||||
Overall Stay – Please rate your overall stay. 5 stars = a great stay!<br />
|
|
||||||
We aim to provide 5-star services to you!
|
|
||||||
</small>
|
|
||||||
<div class="flex justify-center">
|
|
||||||
<StarRating bind:value={overal_star} name="Overall Satisfaction" size="xl" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Checkboxes -->
|
<form
|
||||||
<label class="flex flex-col">
|
on:submit|preventDefault={handleSubmit}
|
||||||
<span class="flex items-center gap-2">
|
class="flex flex-col gap-4 max-w-xl mx-auto p-6 bg-white rounded-xl shadow-md"
|
||||||
<input type="checkbox" bind:checked={extend_disc} />
|
>
|
||||||
<small class="text-sm text-gray-500 mb-1">I would like to discuss extending my stay for 30% off!</small>
|
{#if errorMessage}
|
||||||
</span>
|
<div class="text-red-600 font-semibold">{errorMessage}</div>
|
||||||
</label>
|
{/if}
|
||||||
<label class="flex flex-col">
|
<label for="fb_villaname" class="flex flex-col">Villa Name</label>
|
||||||
<span class="flex items-center gap-2">
|
<input
|
||||||
<input type="checkbox" bind:checked={nextstay_disc} />
|
id="fb_villaname"
|
||||||
<small class="text-sm text-gray-500 mb-1">I would like to discuss booking my next stayto receive an extra discount!</small>
|
type="text"
|
||||||
</span>
|
bind:value={villa_name}
|
||||||
</label>
|
placeholder="Villa Name"
|
||||||
<label class="flex flex-col">
|
required
|
||||||
<span class="flex items-center gap-2">
|
class="p-2 border rounded-md"
|
||||||
<input type="checkbox" bind:checked={become_sponsor} />
|
/>
|
||||||
<small class="text-sm text-gray-500 mb-1">I would like to know more about sponsoring a Balinese child with Damara (for only AU$150 a year!)(100% of the AU$150 goes to the childs schooling - there are no overheads with Damara!)</small>
|
<label for="fb_gn" class="flex flex-col">Name</label>
|
||||||
</span>
|
<input
|
||||||
</label>
|
id="fb_gn"
|
||||||
|
type="text"
|
||||||
<!-- Submit Button -->
|
bind:value={customer_name}
|
||||||
<button type="submit" class="bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 transition">
|
placeholder="Customer Name"
|
||||||
Submit Feedback
|
required
|
||||||
</button>
|
class="p-2 border rounded-md"
|
||||||
</form>
|
/>
|
||||||
|
<label for="fb_cid" class="flex flex-col">Checkin Date</label>
|
||||||
|
<input
|
||||||
|
id="fb_cid"
|
||||||
|
type="date"
|
||||||
|
bind:value={checkin_date}
|
||||||
|
required
|
||||||
|
class="p-2 border rounded-md"
|
||||||
|
/>
|
||||||
|
<label for="fb_cod" class="flex flex-col">Checkout Date</label>
|
||||||
|
<input
|
||||||
|
id="fb_cod"
|
||||||
|
type="date"
|
||||||
|
bind:value={checkout_date}
|
||||||
|
required
|
||||||
|
class="p-2 border rounded-md"
|
||||||
|
/>
|
||||||
|
<!-- Star Ratings -->
|
||||||
|
<label class="flex flex-col">
|
||||||
|
Booking Process:
|
||||||
|
<small class="text-sm text-gray-500 mb-1"
|
||||||
|
>Please highlights of the booking process (anything neglected by the staff
|
||||||
|
or something done well by the staff)</small
|
||||||
|
>
|
||||||
|
<textarea
|
||||||
|
bind:value={book_process}
|
||||||
|
placeholder="Write your feedback here..."
|
||||||
|
required
|
||||||
|
class="p-2 border rounded-md min-h-[120px]"
|
||||||
|
></textarea>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label class="flex flex-col">
|
||||||
|
Airport Greeting and Transportation:
|
||||||
|
<small class="text-sm text-gray-500 mb-1"
|
||||||
|
>Please highlights of the airport transfer experience (anything neglected
|
||||||
|
by the staff or something done well by the staff)</small
|
||||||
|
>
|
||||||
|
<textarea
|
||||||
|
bind:value={airport_greet}
|
||||||
|
placeholder="Write your feedback here..."
|
||||||
|
required
|
||||||
|
class="p-2 border rounded-md min-h-[120px]"
|
||||||
|
></textarea>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label class="flex flex-col">
|
||||||
|
Arrival & Check-in:
|
||||||
|
<small class="text-sm text-gray-500 mb-1"
|
||||||
|
>Please highlights of the arrival and check-in process(anything neglected
|
||||||
|
by the staff or something done well by the staff)</small
|
||||||
|
>
|
||||||
|
<textarea
|
||||||
|
bind:value={arrival_greet}
|
||||||
|
placeholder="Write your feedback here..."
|
||||||
|
required
|
||||||
|
class="p-2 border rounded-md min-h-[120px]"
|
||||||
|
></textarea>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label class="flex flex-col">
|
||||||
|
Breakfast Service or other food and beverage service utilized:
|
||||||
|
<small class="text-sm text-gray-500 mb-1"
|
||||||
|
>Please highlighs of the breakfast service(anything neglected by the staff
|
||||||
|
or something done well by the staff)</small
|
||||||
|
>
|
||||||
|
<textarea
|
||||||
|
bind:value={bf_service}
|
||||||
|
placeholder="Write your feedback here..."
|
||||||
|
required
|
||||||
|
class="p-2 border rounded-md min-h-[120px]"
|
||||||
|
></textarea>
|
||||||
|
</label>
|
||||||
|
<label class="flex flex-col">
|
||||||
|
Housekeeping and Maintenance:
|
||||||
|
<small class="text-sm text-gray-500 mb-1"
|
||||||
|
>Please highlighs of the housekeeping and maintenance service(anything
|
||||||
|
neglected by the staff or something done well by the staff)</small
|
||||||
|
>
|
||||||
|
<textarea
|
||||||
|
bind:value={maintenance_proc}
|
||||||
|
placeholder="Write your feedback here..."
|
||||||
|
required
|
||||||
|
class="p-2 border rounded-md min-h-[120px]"
|
||||||
|
></textarea>
|
||||||
|
</label>
|
||||||
|
<label class="flex flex-col">
|
||||||
|
What did you think of the villa in General:
|
||||||
|
<small class="text-sm text-gray-500 mb-1"
|
||||||
|
>Did you have any other issue of area you would like to highligh during
|
||||||
|
stay? Please let us know any other comments you have - the good, the bad,
|
||||||
|
and the ugly</small
|
||||||
|
>
|
||||||
|
<textarea
|
||||||
|
bind:value={feedback}
|
||||||
|
placeholder="Write your feedback here..."
|
||||||
|
required
|
||||||
|
class="p-2 border rounded-md min-h-[120px]"
|
||||||
|
></textarea>
|
||||||
|
</label>
|
||||||
|
<!-- Centered big star-->
|
||||||
|
<div class="text-center mt-6">
|
||||||
|
<small class="text-sm text-gray-500 block mb-2">
|
||||||
|
Overall Stay – Please rate your overall stay. 5 stars = a great stay!<br
|
||||||
|
/>
|
||||||
|
We aim to provide 5-star services to you!
|
||||||
|
</small>
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<StarRating
|
||||||
|
bind:value={overal_star}
|
||||||
|
name="Overall Satisfaction"
|
||||||
|
size="xl"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Checkboxes -->
|
||||||
|
<label class="flex flex-col">
|
||||||
|
<span class="flex items-center gap-2">
|
||||||
|
<input type="checkbox" bind:checked={extend_disc} />
|
||||||
|
<small class="text-sm text-gray-500 mb-1"
|
||||||
|
>I would like to discuss extending my stay for 30% off!</small
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label class="flex flex-col">
|
||||||
|
<span class="flex items-center gap-2">
|
||||||
|
<input type="checkbox" bind:checked={nextstay_disc} />
|
||||||
|
<small class="text-sm text-gray-500 mb-1"
|
||||||
|
>I would like to discuss booking my next stayto receive an extra
|
||||||
|
discount!</small
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label class="flex flex-col">
|
||||||
|
<span class="flex items-center gap-2">
|
||||||
|
<input type="checkbox" bind:checked={become_sponsor} />
|
||||||
|
<small class="text-sm text-gray-500 mb-1"
|
||||||
|
>I would like to know more about sponsoring a Balinese child with Damara
|
||||||
|
(for only AU$150 a year!)(100% of the AU$150 goes to the childs
|
||||||
|
schooling - there are no overheads with Damara!)</small
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<!-- Submit Button -->
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 transition"
|
||||||
|
>
|
||||||
|
Submit Feedback
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { supabase } from "$lib/supabaseClient";
|
import { supabase } from "$lib/supabaseClient";
|
||||||
import { goto } from "$app/navigation";
|
import { goto } from "$app/navigation";
|
||||||
|
import logo from "$lib/images/villa.png";
|
||||||
|
|
||||||
let email = "";
|
let email = "";
|
||||||
let password = "";
|
let password = "";
|
||||||
@@ -38,11 +39,7 @@
|
|||||||
>
|
>
|
||||||
<!-- Ilustrasi -->
|
<!-- Ilustrasi -->
|
||||||
<div class="hidden md:flex w-1/2 justify-center items-center">
|
<div class="hidden md:flex w-1/2 justify-center items-center">
|
||||||
<img
|
<img src={logo} alt="Login Illustration" class="w-full max-w-sm" />
|
||||||
src="/src/lib/images/villa.png"
|
|
||||||
alt="Login Illustration"
|
|
||||||
class="w-full max-w-sm"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Form Login -->
|
<!-- Form Login -->
|
||||||
|
|||||||
21
src/routes/unauthorized/+page.svelte
Normal file
21
src/routes/unauthorized/+page.svelte
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<script>
|
||||||
|
// Tambahkan script jika ingin menambahkan interaktivitas di masa depan
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="min-h-screen flex items-center justify-center bg-gradient-to-br from-red-100 to-red-300"
|
||||||
|
>
|
||||||
|
<div class="bg-white rounded-xl shadow-lg p-8 max-w-md w-full text-center">
|
||||||
|
<div class="text-6xl mb-4">🚫</div>
|
||||||
|
<h1 class="text-2xl font-bold text-red-600 mb-2">Akses Ditolak</h1>
|
||||||
|
<p class="text-gray-700 mb-6">
|
||||||
|
Anda tidak memiliki izin untuk mengakses halaman ini.
|
||||||
|
</p>
|
||||||
|
<a
|
||||||
|
href="/login"
|
||||||
|
class="inline-block px-6 py-2 rounded-lg bg-red-500 text-white font-semibold hover:bg-red-600 transition"
|
||||||
|
>
|
||||||
|
Kembali ke Login
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user