Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions app/components/AppHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,15 @@
</div>
<nav class="flex-none">
<ul class="menu menu-horizontal px-1">
<li><NuxtLink to="/">Home</NuxtLink></li>
<li><NuxtLink to="/about">About</NuxtLink></li>
<li>
<NuxtLink to="/">Home</NuxtLink>
</li>
<li>
<NuxtLink to="/about">About</NuxtLink>
</li>
<li>
<NuxtLink to="/list">List</NuxtLink>
</li>
</ul>
</nav>
</header>
Expand Down
23 changes: 23 additions & 0 deletions app/components/places/PlaceLink.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script setup lang="ts">
defineProps<{
place: {
id: number;
name: string;
rating: number;
description: string;
};
}>();
</script>

<template>
<NuxtLink
:to="`/place/${place.id}`"
class="block p-4 bg-base-200 border-base-300 rounded-box hover:bg-base-300 transition-colors"
>
<h2 class="text-lg font-semibold">{{ place.name }}</h2>
<p class="text-secondary-content">{{ place.description }}</p>
<div class="mt-2">
<PlacesRatingDisplay :rating="place.rating" />
</div>
</NuxtLink>
</template>
14 changes: 14 additions & 0 deletions app/components/places/RatingDisplay.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script setup lang="ts">
defineProps<{
rating: number;
}>();
</script>

<template>
<div class="flex items-center">
<span v-for="i in 5" :key="i" class="mr-1">
<span :class="i <= rating ? 'text-yellow-500' : 'text-base-content/50'">★</span>
</span>
<span class="ml-2 text-sm text-base-content/80">{{ rating }}</span>
</div>
</template>
24 changes: 24 additions & 0 deletions app/components/places/ReviewCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script setup lang="ts">
defineProps<{
review: {
id: number;
author: string;
rating: number;
comment: string;
date: string;
};
}>();
</script>

<template>
<div class="card card-border">
<div class="card-body space-y-1">
<div class="flex justify-between items-start">
<h3 class="font-semibold">{{ review.author }}</h3>
<span class="text-base-content/50">{{ review.date }}</span>
</div>
<p>{{ review.comment }}</p>
<PlacesRatingDisplay :rating="review.rating" />
</div>
</div>
</template>
18 changes: 18 additions & 0 deletions app/composables/useFakePlaceDataDeletMe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const PLACES = [
{
id: 1,
name: "Moe's tavern",
rating: 4.5,
description: "Cozy local bar with a wide selection of beers and a friendly atmosphere.",
},
{
id: 2,
name: "Kwik-E-Mart",
rating: 3.8,
description: "Convenience store with a variety of groceries and household items.",
},
];

export const useFakePlaceDataDeletMe = () => {
return PLACES;
};
21 changes: 21 additions & 0 deletions app/pages/list.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script setup lang="ts">
/**
* Home page — demonstrates composables, components, and server data fetching.
*
* `useAppInfo()` is auto-imported from `app/composables/`.
* `useFetch` is a Nuxt composable that fetches data during SSR and hydrates
* on the client — no loading spinners needed for the initial render.
*/
import PlaceLink from "~/components/places/PlaceLink.vue";

const PLACES = useFakePlaceDataDeletMe();
</script>

<template>
<div class="container mx-auto p-4">
<h1 class="text-2xl font-bold mb-4">Places</h1>
<div class="flex flex-col gap-1">
<PlaceLink v-for="place in PLACES" :key="place.id" :place="place" />
</div>
</div>
</template>
56 changes: 56 additions & 0 deletions app/pages/place/[id].vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<script setup lang="ts">
const route = useRoute();
const placeId = route.params.id;

const PLACES = useFakePlaceDataDeletMe();
const place = PLACES.find((p) => p.id === Number(placeId));

// Throw 404 if place is not found
if (!place) {
throw createError({
statusCode: 404,
statusMessage: "Place not found",
});
}

// Mock reviews data
const REVIEWS = [
{
id: 1,
author: "John Doe",
rating: 5,
comment: "Great place! The atmosphere is really cozy and the staff is friendly.",
date: "2023-05-15",
},
{
id: 2,
author: "Jane Smith",
rating: 4,
comment: "Good selection of beers. Will definitely come back.",
date: "2023-06-20",
},
{
id: 3,
author: "Bob Johnson",
rating: 3,
comment: "Average place. Nothing too special but decent.",
date: "2023-07-10",
},
];
</script>

<template>
<div class="space-y-8">
<div class="space-y-2 flex align-center flex-col items-center mt-8">
<h1 class="text-3xl font-bold">{{ place.name }}</h1>
<p>{{ place.description }}</p>
<PlacesRatingDisplay :rating="place.rating" />
</div>
<div class="space-y-2">
<h2 class="text-xl font-bold">Reviews</h2>
<div class="space-y-4">
<PlacesReviewCard v-for="review in REVIEWS" :key="review.id" :review="review" />
</div>
</div>
</div>
</template>
24 changes: 23 additions & 1 deletion worker-configuration.d.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
/* eslint-disable */
// Generated by Wrangler by running `wrangler types` (hash: 1224b5b86c5bfbfdc24911a0d4ce5c0f)
// Generated by Wrangler by running `wrangler types` (hash: 933066b3a95ca283951caf6d326d4588)
// Runtime types generated with workerd@1.20260529.1 2026-02-01 no_nodejs_compat_v2,nodejs_compat
interface __BaseEnv_Env {
DB: D1Database;
IMAGES: ImagesBinding;
CF_VERSION_METADATA: WorkerVersionMetadata;
ASSETS: Fetcher;
CLOUDFLARE_ACCOUNT_ID: string;
CLOUDFLARE_DATABASE_ID: string;
CLOUDFLARE_PRODUCTION_DATABASE_ID: string;
CLOUDFLARE_STAGING_DATABASE_ID: string;
CLOUDFLARE_D1_TOKEN: string;
NUXT_SESSION_PASSWORD: string;
}
declare namespace Cloudflare {
interface Env extends __BaseEnv_Env {}
}
interface Env extends __BaseEnv_Env {}
type StringifyValues<EnvType extends Record<string, unknown>> = {
[Binding in keyof EnvType]: EnvType[Binding] extends string ? EnvType[Binding] : string;
};
declare namespace NodeJS {
interface ProcessEnv extends StringifyValues<
Pick<
Cloudflare.Env,
| "CLOUDFLARE_ACCOUNT_ID"
| "CLOUDFLARE_DATABASE_ID"
| "CLOUDFLARE_PRODUCTION_DATABASE_ID"
| "CLOUDFLARE_STAGING_DATABASE_ID"
| "CLOUDFLARE_D1_TOKEN"
| "NUXT_SESSION_PASSWORD"
>
> {}
}

// Begin runtime types
/*! *****************************************************************************
Expand Down