removed dummy data
This commit is contained in:
parent
d5c7d56c11
commit
aba29922c7
|
|
@ -1,21 +0,0 @@
|
||||||
import type { AmenityIconId } from "@/components/icons/AmenityIcon";
|
|
||||||
|
|
||||||
export type AmenityWithIcon = {
|
|
||||||
icon: AmenityIconId;
|
|
||||||
label: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const roomAmenities: AmenityWithIcon[] = [
|
|
||||||
{ icon: "breakfast", label: "B/B Fast" },
|
|
||||||
{ icon: "shuttle", label: "Shuttle" },
|
|
||||||
{ icon: "wifi", label: "Wi‑Fi / LAN" },
|
|
||||||
{ icon: "sparkle", label: "Premium amenities" },
|
|
||||||
{ icon: "tv", label: "IPTV" },
|
|
||||||
{ icon: "kitchen", label: "State of the art kitchenette" },
|
|
||||||
{ icon: "views", label: "Amazing views" },
|
|
||||||
{ icon: "minibar", label: "Mini bar" },
|
|
||||||
{ icon: "lock", label: "Safe boxes" },
|
|
||||||
{ icon: "iron", label: "Iron & board" },
|
|
||||||
{ icon: "router", label: "Private routers" },
|
|
||||||
{ icon: "laundry", label: "Laundry (paid services)" },
|
|
||||||
];
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
function delay(ms: number) {
|
|
||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
||||||
}
|
|
||||||
|
|
||||||
export type BookingPayload = {
|
|
||||||
roomId: string;
|
|
||||||
email: string;
|
|
||||||
flightBookingNumber: string;
|
|
||||||
arrivalTime: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type PaymentPayload = {
|
|
||||||
totalCents: number;
|
|
||||||
last4?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function submitBookingHold(
|
|
||||||
payload: BookingPayload,
|
|
||||||
): Promise<{ reference: string }> {
|
|
||||||
void payload;
|
|
||||||
await delay(900 + Math.random() * 400);
|
|
||||||
return {
|
|
||||||
reference: `SHY-${Date.now().toString(36).toUpperCase()}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function processPayment(
|
|
||||||
payload: PaymentPayload,
|
|
||||||
): Promise<{ confirmationId: string; paidAt: string }> {
|
|
||||||
void payload;
|
|
||||||
await delay(1100 + Math.random() * 500);
|
|
||||||
const id =
|
|
||||||
typeof crypto !== "undefined" && crypto.randomUUID
|
|
||||||
? crypto.randomUUID().slice(0, 8)
|
|
||||||
: Math.random().toString(36).slice(2, 10);
|
|
||||||
const confirmationId = `PAY-${id.toUpperCase()}`;
|
|
||||||
return {
|
|
||||||
confirmationId,
|
|
||||||
paidAt: new Date().toISOString(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
/**
|
|
||||||
* Illustrative guest reviews shown in the nav — style inspired by Booking.com.
|
|
||||||
* Replace copy/URLs with live data from your Booking.com property page when available.
|
|
||||||
*/
|
|
||||||
export type BookingStyleReview = {
|
|
||||||
id: string;
|
|
||||||
author: string;
|
|
||||||
country: string;
|
|
||||||
rating: number;
|
|
||||||
maxRating: number;
|
|
||||||
title: string;
|
|
||||||
text: string;
|
|
||||||
stayDate: string;
|
|
||||||
roomType: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const bookingStyleReviews: BookingStyleReview[] = [
|
|
||||||
{
|
|
||||||
id: "1",
|
|
||||||
author: "Sarah M.",
|
|
||||||
country: "United Kingdom",
|
|
||||||
rating: 9.2,
|
|
||||||
maxRating: 10,
|
|
||||||
title: "Exceptional stay in Addis",
|
|
||||||
text: "Spotless suites, attentive team, and a perfect base for meetings. Breakfast at FeastVille was a highlight — we’ll return.",
|
|
||||||
stayDate: "October 2025",
|
|
||||||
roomType: "Connecting Suite",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "2",
|
|
||||||
author: "Daniel K.",
|
|
||||||
country: "Germany",
|
|
||||||
rating: 8.8,
|
|
||||||
maxRating: 10,
|
|
||||||
title: "Great location & comfort",
|
|
||||||
text: "Quiet rooms, strong Wi‑Fi, and easy access to the city. The junior studio had everything we needed for a week of work.",
|
|
||||||
stayDate: "September 2025",
|
|
||||||
roomType: "Junior Studio",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "3",
|
|
||||||
author: "Hanna T.",
|
|
||||||
country: "Ethiopia",
|
|
||||||
rating: 9.6,
|
|
||||||
maxRating: 10,
|
|
||||||
title: "Family trip made easy",
|
|
||||||
text: "We booked the penthouse for a celebration — space, views, and service exceeded expectations. Kids loved the IPTV selection.",
|
|
||||||
stayDate: "August 2025",
|
|
||||||
roomType: "4 Bedroom Penthouse",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export function averageBookingStyleRating(
|
|
||||||
list: BookingStyleReview[] = bookingStyleReviews,
|
|
||||||
): number {
|
|
||||||
if (!list.length) return 0;
|
|
||||||
const sum = list.reduce((a, r) => a + r.rating, 0);
|
|
||||||
return Math.round((sum / list.length) * 10) / 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Aggregate score shown in the reviews dialog (out of 5), with circle “star” row */
|
|
||||||
export const overallRatingOutOfFive = 4.5;
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
/** Demo booking references — any guest can use these in mock mode. */
|
|
||||||
export const DEMO_BOOKING_REFS: Record<
|
|
||||||
string,
|
|
||||||
{ guestName: string; room: string; checkOut: string }
|
|
||||||
> = {
|
|
||||||
"SHITAYE-2026-DEMO": {
|
|
||||||
guestName: "Demo Guest",
|
|
||||||
room: "Junior Studio · 1204",
|
|
||||||
checkOut: "2026-04-12",
|
|
||||||
},
|
|
||||||
"GUEST-1234": {
|
|
||||||
guestName: "Abebe T.",
|
|
||||||
room: "Standard King · 805",
|
|
||||||
checkOut: "2026-04-09",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export type MockAppointment = {
|
|
||||||
id: string;
|
|
||||||
title: string;
|
|
||||||
when: string;
|
|
||||||
where: string;
|
|
||||||
status: "confirmed" | "pending";
|
|
||||||
};
|
|
||||||
|
|
||||||
export type MockShuttle = {
|
|
||||||
/** ISO date */
|
|
||||||
departureDate: string;
|
|
||||||
/** e.g. "04:15" */
|
|
||||||
lobbyPickupTime: string;
|
|
||||||
/** e.g. "Bole International (ADD)" */
|
|
||||||
airport: string;
|
|
||||||
flightLabel: string;
|
|
||||||
notes: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type MockReward = {
|
|
||||||
id: string;
|
|
||||||
label: string;
|
|
||||||
points: number;
|
|
||||||
earnedAt: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const seedAppointments: MockAppointment[] = [
|
|
||||||
{
|
|
||||||
id: "a1",
|
|
||||||
title: "Deep tissue massage",
|
|
||||||
when: "Today · 16:30",
|
|
||||||
where: "Spa · Treatment suite B",
|
|
||||||
status: "confirmed",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "a2",
|
|
||||||
title: "Small-group HIIT",
|
|
||||||
when: "Tomorrow · 07:00",
|
|
||||||
where: "Fitness centre · Studio",
|
|
||||||
status: "confirmed",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const seedShuttle: MockShuttle = {
|
|
||||||
departureDate: "2026-04-11",
|
|
||||||
lobbyPickupTime: "04:15",
|
|
||||||
airport: "Bole International (ADD)",
|
|
||||||
flightLabel: "ET 302 · Addis → Frankfurt",
|
|
||||||
notes: "Please be in the lobby 10 minutes early. Shuttle is complimentary for this stay.",
|
|
||||||
};
|
|
||||||
|
|
||||||
export const seedRewardsHistory: MockReward[] = [
|
|
||||||
{
|
|
||||||
id: "r1",
|
|
||||||
label: "Welcome bonus — direct booking",
|
|
||||||
points: 500,
|
|
||||||
earnedAt: "2026-04-01",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "r2",
|
|
||||||
label: "Room service order",
|
|
||||||
points: 40,
|
|
||||||
earnedAt: "2026-04-03",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "r3",
|
|
||||||
label: "Spa visit",
|
|
||||||
points: 120,
|
|
||||||
earnedAt: "2026-04-04",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
export type LaundryItem = {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
priceUsd: number;
|
|
||||||
unit: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const laundryItems: LaundryItem[] = [
|
|
||||||
{
|
|
||||||
id: "l-1",
|
|
||||||
name: "Shirt / blouse",
|
|
||||||
description: "Pressed",
|
|
||||||
priceUsd: 4,
|
|
||||||
unit: "each",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "l-2",
|
|
||||||
name: "Trousers / skirt",
|
|
||||||
description: "Pressed",
|
|
||||||
priceUsd: 5,
|
|
||||||
unit: "each",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "l-3",
|
|
||||||
name: "Suit (2 pc)",
|
|
||||||
description: "Clean & press",
|
|
||||||
priceUsd: 18,
|
|
||||||
unit: "set",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "l-4",
|
|
||||||
name: "Dress",
|
|
||||||
description: "Delicate cycle",
|
|
||||||
priceUsd: 12,
|
|
||||||
unit: "each",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "l-5",
|
|
||||||
name: "Express (same day)",
|
|
||||||
description: "Surcharge on top of item prices",
|
|
||||||
priceUsd: 15,
|
|
||||||
unit: "per order",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
import type { AmenityWithIcon } from "./amenities";
|
|
||||||
|
|
||||||
export type MeetingSpace = {
|
|
||||||
slug: string;
|
|
||||||
name: string;
|
|
||||||
shortDescription: string;
|
|
||||||
longDescription: string;
|
|
||||||
capacity: string;
|
|
||||||
floor: string;
|
|
||||||
image: string;
|
|
||||||
gallery: string[];
|
|
||||||
amenities: AmenityWithIcon[];
|
|
||||||
layouts: string[];
|
|
||||||
catering: string[];
|
|
||||||
/** Mock half-day rate in USD for display (converted via currency switcher) */
|
|
||||||
halfDayRateUsd: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const meetingSpaces: MeetingSpace[] = [
|
|
||||||
{
|
|
||||||
slug: "serenity",
|
|
||||||
name: "Serenity Meeting Room",
|
|
||||||
shortDescription: "Versatile event space for up to 100 guests on the 1st floor.",
|
|
||||||
longDescription:
|
|
||||||
"Serenity is designed for board sessions, cocktail receptions, and medium-scale corporate events. Natural light options, flexible seating, and dedicated support for AV and catering make it the hotel’s flagship meeting venue.",
|
|
||||||
capacity: "Up to 100 guests (theatre / cocktail configurations)",
|
|
||||||
floor: "1st floor",
|
|
||||||
image:
|
|
||||||
"https://images.unsplash.com/photo-1497366216548-37526070297c?w=1200&q=80",
|
|
||||||
gallery: [
|
|
||||||
"https://images.unsplash.com/photo-1497366216548-37526070297c?w=1200&q=80",
|
|
||||||
"https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?w=1200&q=80",
|
|
||||||
"https://images.unsplash.com/photo-1511578314322-379afb476865?w=1200&q=80",
|
|
||||||
],
|
|
||||||
amenities: [
|
|
||||||
{ icon: "wifi", label: "High-speed Wi‑Fi / LAN" },
|
|
||||||
{ icon: "projector", label: "Projector & screen" },
|
|
||||||
{ icon: "microphone", label: "Wireless microphones" },
|
|
||||||
{ icon: "clipboard", label: "Flip charts & stationery" },
|
|
||||||
{ icon: "thermometer", label: "Climate control" },
|
|
||||||
{ icon: "handshake", label: "Dedicated event coordinator (on request)" },
|
|
||||||
{ icon: "doorOpen", label: "Breakout foyer access" },
|
|
||||||
{ icon: "accessibility", label: "Accessible routes" },
|
|
||||||
],
|
|
||||||
layouts: ["Boardroom", "U-shape", "Theatre", "Classroom", "Cocktail / standing"],
|
|
||||||
catering: ["Buffet menus", "Tea & coffee breaks", "Working lunch packages", "Gala dinner (via FeastVille)"],
|
|
||||||
halfDayRateUsd: 850,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: "fasika",
|
|
||||||
name: "Fasika Board Room",
|
|
||||||
shortDescription: "Executive board room for 25–30 guests — intimate and fully equipped.",
|
|
||||||
longDescription:
|
|
||||||
"Fasika offers privacy and polish for leadership offsites, signing ceremonies, and focused workshops. Sound-treated walls, ergonomic seating, and premium coffee service keep sessions productive.",
|
|
||||||
capacity: "25–30 guests (boardroom style)",
|
|
||||||
floor: "1st floor",
|
|
||||||
image:
|
|
||||||
"https://images.unsplash.com/photo-1560179707-f14e90ef3623?w=1200&q=80",
|
|
||||||
gallery: [
|
|
||||||
"https://images.unsplash.com/photo-1560179707-f14e90ef3623?w=1200&q=80",
|
|
||||||
"https://images.unsplash.com/photo-1542744173-8e7e53415bb0?w=1200&q=80",
|
|
||||||
"https://images.unsplash.com/photo-1600880292203-757bb62b4baf?w=1200&q=80",
|
|
||||||
],
|
|
||||||
amenities: [
|
|
||||||
{ icon: "monitor", label: "4K display & HDMI / USB-C" },
|
|
||||||
{ icon: "video", label: "Video-conferencing ready" },
|
|
||||||
{ icon: "chair", label: "Executive leather seating" },
|
|
||||||
{ icon: "volumeMuted", label: "Sound dampening" },
|
|
||||||
{ icon: "restroom", label: "Private washroom adjacency" },
|
|
||||||
{ icon: "pen", label: "Notepads & pens" },
|
|
||||||
{ icon: "droplet", label: "Complimentary mineral water" },
|
|
||||||
{ icon: "phone", label: "Dedicated phone line (on request)" },
|
|
||||||
],
|
|
||||||
layouts: ["Boardroom", "Interview (2–4 pax)", "Small workshop"],
|
|
||||||
catering: ["Executive breakfast", "Coffee & pastries", "Light lunch boxes"],
|
|
||||||
halfDayRateUsd: 420,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export function getMeetingSpaceBySlug(slug: string): MeetingSpace | undefined {
|
|
||||||
return meetingSpaces.find((m) => m.slug === slug);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getAllMeetingSlugs(): string[] {
|
|
||||||
return meetingSpaces.map((m) => m.slug);
|
|
||||||
}
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
export type Outlet = {
|
|
||||||
slug: string;
|
|
||||||
name: string;
|
|
||||||
tagline: string;
|
|
||||||
bullets: string[];
|
|
||||||
image: string;
|
|
||||||
floor?: string;
|
|
||||||
/** Link to detail page when set (e.g. meeting rooms) */
|
|
||||||
detailHref?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const outlets: Outlet[] = [
|
|
||||||
{
|
|
||||||
slug: "feastville",
|
|
||||||
name: "FeastVille Restaurant",
|
|
||||||
tagline: "Full American breakfast to theme nights — savour every moment.",
|
|
||||||
bullets: [
|
|
||||||
"Full American breakfast",
|
|
||||||
"Traditional & international menu",
|
|
||||||
"Theme nights selection",
|
|
||||||
"Room service menu",
|
|
||||||
],
|
|
||||||
image:
|
|
||||||
"https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=1200&q=80",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: "central-cafe",
|
|
||||||
name: "Central Cafe",
|
|
||||||
tagline: "Purely urban vibes — coffee at the heart of the city.",
|
|
||||||
bullets: [
|
|
||||||
"Your perfect rendezvous in the city centre",
|
|
||||||
"Ideal to initiate, elevate & conclude your day",
|
|
||||||
],
|
|
||||||
image:
|
|
||||||
"https://images.unsplash.com/photo-1501339847302-ac426a4a7cbb?w=1200&q=80",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: "tabsia",
|
|
||||||
name: "TABSIA Bar",
|
|
||||||
tagline: "Cocktails, spirits, and a refined atmosphere.",
|
|
||||||
bullets: [
|
|
||||||
"Located on the 1st floor",
|
|
||||||
"Cocktails, spirits & more",
|
|
||||||
"Unwind after a long day",
|
|
||||||
],
|
|
||||||
floor: "1st floor",
|
|
||||||
image:
|
|
||||||
"https://images.unsplash.com/photo-1551024506-0bccd828d307?w=1200&q=80&auto=format&fit=crop",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: "serenity",
|
|
||||||
name: "Serenity Meeting Room",
|
|
||||||
tagline: "Board meetings, cocktails, and events up to 100 guests.",
|
|
||||||
bullets: [
|
|
||||||
"Up to 100 pax",
|
|
||||||
"Fully equipped with basics & stationeries",
|
|
||||||
"Buffet or tea break menus",
|
|
||||||
],
|
|
||||||
floor: "1st floor",
|
|
||||||
detailHref: "/meetings/serenity",
|
|
||||||
image:
|
|
||||||
"https://images.unsplash.com/photo-1497366216548-37526070297c?w=1200&q=80",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
slug: "fasika",
|
|
||||||
name: "Fasika Board Room",
|
|
||||||
tagline: "Intimate executive sessions for 25–30 guests.",
|
|
||||||
bullets: [
|
|
||||||
"25–30 pax",
|
|
||||||
"Board & cocktail setups",
|
|
||||||
"Equipment & catering options",
|
|
||||||
],
|
|
||||||
floor: "1st floor",
|
|
||||||
detailHref: "/meetings/fasika",
|
|
||||||
image:
|
|
||||||
"https://images.unsplash.com/photo-1560179707-f14e90ef3623?w=1200&q=80",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
export type MenuCategory = "breakfast" | "mains" | "desserts" | "beverages";
|
|
||||||
|
|
||||||
export const roomServiceCategories: { id: MenuCategory; label: string }[] = [
|
|
||||||
{ id: "breakfast", label: "Breakfast" },
|
|
||||||
{ id: "mains", label: "Mains & light bites" },
|
|
||||||
{ id: "desserts", label: "Desserts" },
|
|
||||||
{ id: "beverages", label: "Beverages" },
|
|
||||||
];
|
|
||||||
|
|
||||||
export type MenuItem = {
|
|
||||||
id: string;
|
|
||||||
category: MenuCategory;
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
priceUsd: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const roomServiceItems: MenuItem[] = [
|
|
||||||
{
|
|
||||||
id: "bf-1",
|
|
||||||
category: "breakfast",
|
|
||||||
name: "Full American breakfast",
|
|
||||||
description: "Eggs any style, beef bacon, chicken sausage, beans, toast, juice, coffee.",
|
|
||||||
priceUsd: 18,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "bf-2",
|
|
||||||
category: "breakfast",
|
|
||||||
name: "Ethiopian breakfast platter",
|
|
||||||
description: "Injera, spiced lentils, fresh cheese, honey, seasonal fruit.",
|
|
||||||
priceUsd: 14,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "mn-1",
|
|
||||||
category: "mains",
|
|
||||||
name: "Grilled salmon",
|
|
||||||
description: "Herb butter, seasonal vegetables, lemon.",
|
|
||||||
priceUsd: 28,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "mn-2",
|
|
||||||
category: "mains",
|
|
||||||
name: "Beef tibs",
|
|
||||||
description: "Traditional sauté with peppers, injera or rice.",
|
|
||||||
priceUsd: 22,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "ds-1",
|
|
||||||
category: "desserts",
|
|
||||||
name: "Chocolate fondant",
|
|
||||||
description: "Warm centre, vanilla ice cream.",
|
|
||||||
priceUsd: 12,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "bv-1",
|
|
||||||
category: "beverages",
|
|
||||||
name: "Fresh juice",
|
|
||||||
description: "Orange, mango, or mixed.",
|
|
||||||
priceUsd: 6,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "bv-2",
|
|
||||||
category: "beverages",
|
|
||||||
name: "Ethiopian coffee ceremony (2)",
|
|
||||||
description: "Traditional preparation — allow 20 min.",
|
|
||||||
priceUsd: 15,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
export type Room = {
|
|
||||||
id: string;
|
|
||||||
slug: string;
|
|
||||||
name: string;
|
|
||||||
shortDescription: string;
|
|
||||||
longDescription: string;
|
|
||||||
nightlyRate: number;
|
|
||||||
maxGuests: number;
|
|
||||||
beds: string;
|
|
||||||
sizeSqM: number;
|
|
||||||
view: string;
|
|
||||||
highlights: string[];
|
|
||||||
gallery: string[];
|
|
||||||
tourEmbedUrl: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const rooms: Room[] = [
|
|
||||||
{
|
|
||||||
id: "penthouse",
|
|
||||||
slug: "four-bedroom-penthouse",
|
|
||||||
name: "The 4 Bedroom Penthouse",
|
|
||||||
shortDescription: "Our flagship residence with panoramic views and full kitchenette.",
|
|
||||||
longDescription:
|
|
||||||
"Experience elevated living in our four-bedroom penthouse — expansive layouts, state-of-the-art kitchenette, and amazing views over Addis Ababa. Ideal for extended stays and distinguished guests who expect space, privacy, and premium finishes.",
|
|
||||||
nightlyRate: 485,
|
|
||||||
maxGuests: 8,
|
|
||||||
beds: "4 bedrooms — mix of king and twin configurations",
|
|
||||||
sizeSqM: 220,
|
|
||||||
view: "City skyline",
|
|
||||||
highlights: ["Private routers", "IPTV", "Mini bar", "In-room safe"],
|
|
||||||
gallery: [
|
|
||||||
"https://images.unsplash.com/photo-1618773928121-c32242e63f39?w=1200&q=80&auto=format&fit=crop",
|
|
||||||
"https://images.unsplash.com/photo-1631049307264-da0ec9d70304?w=1200&q=80&auto=format&fit=crop",
|
|
||||||
"https://images.unsplash.com/photo-1582719478250-c89cae4dc85b?w=1200&q=80&auto=format&fit=crop",
|
|
||||||
],
|
|
||||||
tourEmbedUrl: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "standard",
|
|
||||||
slug: "standard-rooms",
|
|
||||||
name: "Standard Rooms",
|
|
||||||
shortDescription: "Refined comfort with every essential amenity.",
|
|
||||||
longDescription:
|
|
||||||
"Our standard rooms combine restful design with practical luxury: premium bedding, dedicated workspace, IPTV, and seamless Wi‑Fi / LAN. Perfect for business and leisure travellers who value consistency and calm.",
|
|
||||||
nightlyRate: 120,
|
|
||||||
maxGuests: 2,
|
|
||||||
beds: "1 King or 2 Twin",
|
|
||||||
sizeSqM: 28,
|
|
||||||
view: "City or courtyard",
|
|
||||||
highlights: ["B/B fast", "Iron & board", "Laundry (paid)", "Safe box"],
|
|
||||||
gallery: [
|
|
||||||
"https://images.unsplash.com/photo-1590490360182-c33d57733427?w=1200&q=80",
|
|
||||||
"https://images.unsplash.com/photo-1566665797739-1674de7a215a?w=1200&q=80",
|
|
||||||
],
|
|
||||||
tourEmbedUrl: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "connecting-suite",
|
|
||||||
slug: "connecting-suite",
|
|
||||||
name: "Connecting Suite",
|
|
||||||
shortDescription: "Flexible suites — convert to a spacious family layout.",
|
|
||||||
longDescription:
|
|
||||||
"Connecting suite rooms with the option of converting to family suites. Enjoy separate living and sleeping zones, kitchenette access where applicable, and the same premium amenities found across the property.",
|
|
||||||
nightlyRate: 210,
|
|
||||||
maxGuests: 5,
|
|
||||||
beds: "1 King + connecting twin room",
|
|
||||||
sizeSqM: 55,
|
|
||||||
view: "City",
|
|
||||||
highlights: ["Family-friendly layout", "Kitchenette", "IPTV", "Shuttle"],
|
|
||||||
gallery: [
|
|
||||||
"https://images.unsplash.com/photo-1618773928121-c32242e63f39?w=1200&q=80",
|
|
||||||
"https://images.unsplash.com/photo-1591088398332-8a7791972843?w=1200&q=80",
|
|
||||||
],
|
|
||||||
tourEmbedUrl: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "junior-studio",
|
|
||||||
slug: "junior-studios",
|
|
||||||
name: "Junior Studios",
|
|
||||||
shortDescription: "Compact sophistication for solo travellers and short stays.",
|
|
||||||
longDescription:
|
|
||||||
"Junior studios offer a smart open plan with kitchenette, premium Wi‑Fi, IPTV, and efficient storage — designed for guests who want independence without sacrificing hotel service.",
|
|
||||||
nightlyRate: 95,
|
|
||||||
maxGuests: 2,
|
|
||||||
beds: "1 Queen",
|
|
||||||
sizeSqM: 32,
|
|
||||||
view: "Urban",
|
|
||||||
highlights: ["Kitchenette", "Mini bar", "Private router option"],
|
|
||||||
gallery: [
|
|
||||||
"https://images.unsplash.com/photo-1522771739844-6a9f6d5f14af?w=1200&q=80",
|
|
||||||
"https://images.unsplash.com/photo-1502672260266-1c1ef2d93688?w=1200&q=80",
|
|
||||||
],
|
|
||||||
tourEmbedUrl: null,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export function getRoomBySlug(slug: string): Room | undefined {
|
|
||||||
return rooms.find((r) => r.slug === slug);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getAllRoomSlugs(): string[] {
|
|
||||||
return rooms.map((r) => r.slug);
|
|
||||||
}
|
|
||||||
|
|
@ -1,108 +0,0 @@
|
||||||
/**
|
|
||||||
* Bookable Spa & Gym offerings for the dedicated /services page (mock pricing).
|
|
||||||
*/
|
|
||||||
export type SpaGymKind = "spa" | "gym";
|
|
||||||
|
|
||||||
export type SpaGymService = {
|
|
||||||
id: string;
|
|
||||||
kind: SpaGymKind;
|
|
||||||
title: string;
|
|
||||||
description: string;
|
|
||||||
duration: string;
|
|
||||||
priceUsd: number;
|
|
||||||
/** Shown on card badge, e.g. "per session" */
|
|
||||||
priceNote: string;
|
|
||||||
image: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const spaGymFilterIds = ["all", "spa", "gym"] as const;
|
|
||||||
export type SpaGymFilterId = (typeof spaGymFilterIds)[number];
|
|
||||||
|
|
||||||
export const spaGymFilters: { id: SpaGymFilterId; label: string }[] = [
|
|
||||||
{ id: "all", label: "All" },
|
|
||||||
{ id: "spa", label: "Spa" },
|
|
||||||
{ id: "gym", label: "Gym" },
|
|
||||||
];
|
|
||||||
|
|
||||||
export const spaGymServices: SpaGymService[] = [
|
|
||||||
{
|
|
||||||
id: "gym-day-pass",
|
|
||||||
kind: "gym",
|
|
||||||
title: "Fitness day pass",
|
|
||||||
description: "Full access to cardio, weights, and stretch zones for one calendar day.",
|
|
||||||
duration: "All day · 6:00 — 22:00",
|
|
||||||
priceUsd: 18,
|
|
||||||
priceNote: "per guest / day",
|
|
||||||
image: "https://images.unsplash.com/photo-1534438327276-14e5300c3a48?w=900&q=80",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "gym-pt",
|
|
||||||
kind: "gym",
|
|
||||||
title: "Personal training",
|
|
||||||
description: "One-on-one session tailored to your goals — form, intensity, and recovery.",
|
|
||||||
duration: "45 minutes",
|
|
||||||
priceUsd: 55,
|
|
||||||
priceNote: "per session",
|
|
||||||
image: "https://images.unsplash.com/photo-1571019614242-c5c5dee9f50b?w=900&q=80",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "gym-hiit",
|
|
||||||
kind: "gym",
|
|
||||||
title: "Small-group HIIT",
|
|
||||||
description: "High-energy class in our studio — limited spots, hotel guests priority.",
|
|
||||||
duration: "50 minutes",
|
|
||||||
priceUsd: 28,
|
|
||||||
priceNote: "per class",
|
|
||||||
image: "https://images.unsplash.com/photo-1517836357463-d25dfeac3438?w=900&q=80",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "spa-swedish",
|
|
||||||
kind: "spa",
|
|
||||||
title: "Signature Swedish massage",
|
|
||||||
description: "Long, flowing strokes to ease travel tension and improve circulation.",
|
|
||||||
duration: "60 minutes",
|
|
||||||
priceUsd: 85,
|
|
||||||
priceNote: "per treatment",
|
|
||||||
image: "https://images.unsplash.com/photo-1544161515-4ab6ce6db874?w=900&q=80",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "spa-deep",
|
|
||||||
kind: "spa",
|
|
||||||
title: "Deep tissue therapy",
|
|
||||||
description: "Targeted work for shoulders, back, and legs after long flights.",
|
|
||||||
duration: "90 minutes",
|
|
||||||
priceUsd: 125,
|
|
||||||
priceNote: "per treatment",
|
|
||||||
image: "https://images.unsplash.com/photo-1600334129128-0c9b275703e6?w=900&q=80",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "spa-express",
|
|
||||||
kind: "spa",
|
|
||||||
title: "Express back & neck",
|
|
||||||
description: "Focused relief when you’re between meetings — clothes-on option.",
|
|
||||||
duration: "30 minutes",
|
|
||||||
priceUsd: 52,
|
|
||||||
priceNote: "per treatment",
|
|
||||||
image: "https://images.unsplash.com/photo-1519823551278-64ac92734fb1?w=900&q=80",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "spa-aroma",
|
|
||||||
kind: "spa",
|
|
||||||
title: "Aromatherapy ritual",
|
|
||||||
description: "Custom oil blend, warm compress, and full-body massage sequence.",
|
|
||||||
duration: "75 minutes",
|
|
||||||
priceUsd: 98,
|
|
||||||
priceNote: "per treatment",
|
|
||||||
image: "https://images.unsplash.com/photo-1540555700478-4be289fbecef?w=900&q=80",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "spa-couples",
|
|
||||||
kind: "spa",
|
|
||||||
title: "Couples’ suite ritual",
|
|
||||||
description: "Side-by-side massage in our private suite — sparkling water included.",
|
|
||||||
duration: "90 minutes",
|
|
||||||
priceUsd: 220,
|
|
||||||
priceNote: "per couple",
|
|
||||||
image: "https://images.unsplash.com/photo-1600334089648-b0d9d3028eb2?w=900&q=80",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
/** Site-wide mock config — replace embed URLs when real Matterport/360 tours exist. */
|
|
||||||
export const siteConfig = {
|
|
||||||
name: "Shitaye Suite Hotel",
|
|
||||||
tagline: "The Unwinding Choice",
|
|
||||||
city: "Addis Ababa",
|
|
||||||
address: "Ethio China Street, Kirkos, Addis Ababa, Ethiopia",
|
|
||||||
/** Google Maps — search result embed (hotel place). */
|
|
||||||
googleMapsEmbedUrl:
|
|
||||||
"https://www.google.com/maps?q=Shitaye+Suite+Hotel+Addis+Ababa+Ethiopia&output=embed&z=16",
|
|
||||||
/** Opens Google Maps with directions to the hotel (destination preset). */
|
|
||||||
googleMapsDirectionsUrl:
|
|
||||||
"https://www.google.com/maps/dir/?api=1&destination=Shitaye+Suite+Hotel+Ethio+China+Street+Kirkos+Addis+Ababa+Ethiopia",
|
|
||||||
/** Place search — opens the hotel pin in Google Maps (not directions mode). */
|
|
||||||
googleMapsPlaceUrl:
|
|
||||||
"https://www.google.com/maps/search/?api=1&query=Shitaye+Suite+Hotel+Addis+Ababa+Ethiopia",
|
|
||||||
phones: ["+251 96 688 4400", "+251 96 688 2200", "+251 11 46 21000"],
|
|
||||||
/** Primary number shown on FAB / quick call */
|
|
||||||
primaryPhone: "+251 96 688 4400",
|
|
||||||
email: "reservation@shitayesuitehotel.com",
|
|
||||||
/** Departments (from official site) */
|
|
||||||
departments: [
|
|
||||||
{ label: "Marketing", phones: ["+251 96 688 4400", "+251 96 688 2200"] },
|
|
||||||
{ label: "Reception", phones: ["+251 11 46 21000"] },
|
|
||||||
],
|
|
||||||
videoTourUrl: "https://www.youtube.com/watch?v=oH4hH1P7vdM",
|
|
||||||
hotelTourEmbedUrl: null as string | null,
|
|
||||||
/** Property listing (guest reviews, photos) */
|
|
||||||
bookingComReviewsUrl: "https://www.booking.com/hotel/et/shitaye-suite.html",
|
|
||||||
/**
|
|
||||||
* Lobby / lounge photo from the Booking.com gallery (same listing as above).
|
|
||||||
* Caption on Booking: living area with seating — property-authentic asset.
|
|
||||||
*/
|
|
||||||
lobbyImageUrl:
|
|
||||||
"https://cf.bstatic.com/xdata/images/hotel/max1024x768/536142684.jpg?k=e550cdbc87e2b08b7fd6b261d0c719149024f47369a5f53a628fca9630631bb6&o=",
|
|
||||||
social: {
|
|
||||||
facebook: "https://www.facebook.com/shitayesuitehotel/",
|
|
||||||
twitter: "https://twitter.com/ShitayeSuite",
|
|
||||||
whatsapp: "https://wa.me/0966884400",
|
|
||||||
instagram: "https://instagram.com/shitaye_suite_hotel",
|
|
||||||
},
|
|
||||||
taxRate: 0.15,
|
|
||||||
};
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
import type { AmenityWithIcon } from "./amenities";
|
|
||||||
|
|
||||||
export type WellnessFacility = {
|
|
||||||
id: string;
|
|
||||||
title: string;
|
|
||||||
subtitle: string;
|
|
||||||
description: string;
|
|
||||||
image: string;
|
|
||||||
amenities: AmenityWithIcon[];
|
|
||||||
hours: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const wellnessFacilities: WellnessFacility[] = [
|
|
||||||
{
|
|
||||||
id: "gym",
|
|
||||||
title: "Fitness centre",
|
|
||||||
subtitle: "Train on your schedule",
|
|
||||||
description:
|
|
||||||
"Cardio machines, free weights, and functional training space — maintained daily and stocked with fresh towels and chilled water. Perfect before meetings or after long flights.",
|
|
||||||
image:
|
|
||||||
"https://images.unsplash.com/photo-1534438327276-14e5300c3a48?w=1200&q=80",
|
|
||||||
amenities: [
|
|
||||||
{ icon: "treadmill", label: "Treadmills & ellipticals" },
|
|
||||||
{ icon: "dumbbell", label: "Dumbbells & kettlebells" },
|
|
||||||
{ icon: "stretch", label: "Stretching zone" },
|
|
||||||
{ icon: "towel", label: "Towel service" },
|
|
||||||
{ icon: "headphones", label: "Bluetooth audio (personal headsets)" },
|
|
||||||
],
|
|
||||||
hours: "6:00 — 22:00 daily",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "spa",
|
|
||||||
title: "Spa & wellness",
|
|
||||||
subtitle: "Restore and unwind",
|
|
||||||
description:
|
|
||||||
"Therapeutic massages, express treatments, and calming lounges inspired by Ethiopian botanicals. Book ahead for couples’ rituals or post-event recovery sessions.",
|
|
||||||
image:
|
|
||||||
"https://images.unsplash.com/photo-1540555700478-4be289fbecef?w=1200&q=80",
|
|
||||||
amenities: [
|
|
||||||
{ icon: "massage", label: "Signature massage menu" },
|
|
||||||
{ icon: "steam", label: "Steam experience (select days)" },
|
|
||||||
{ icon: "leaf", label: "Aromatherapy add-ons" },
|
|
||||||
{ icon: "lounge", label: "Private treatment suites" },
|
|
||||||
{ icon: "boutique", label: "Retail boutique" },
|
|
||||||
],
|
|
||||||
hours: "10:00 — 20:00 · appointments recommended",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
Loading…
Reference in New Issue
Block a user