diff --git a/nextjs-end/.prettierrc.json b/nextjs-end/.prettierrc.json
index 48c545c5..be084604 100644
--- a/nextjs-end/.prettierrc.json
+++ b/nextjs-end/.prettierrc.json
@@ -1,8 +1,5 @@
{
"trailingComma": "all",
"semi": true,
- "tabWidth": 2,
- "singleQuote": true,
- "jsxSingleQuote": true,
- "plugins": []
+ "tabWidth": 2
}
diff --git a/nextjs-end/auth-service-worker.js b/nextjs-end/auth-service-worker.js
index b24d82cc..c7945c70 100644
--- a/nextjs-end/auth-service-worker.js
+++ b/nextjs-end/auth-service-worker.js
@@ -1,13 +1,13 @@
-import { initializeApp } from 'firebase/app';
-import { getAuth, getIdToken, onAuthStateChanged } from 'firebase/auth';
+import { initializeApp } from "firebase/app";
+import { getAuth, getIdToken, onAuthStateChanged } from "firebase/auth";
// extract firebase config from query string
const serializedFirebaseConfig = new URLSearchParams(self.location.search).get(
- 'firebaseConfig',
+ "firebaseConfig",
);
if (!serializedFirebaseConfig) {
throw new Error(
- 'Firebase Config object not found in service worker query string.',
+ "Firebase Config object not found in service worker query string.",
);
}
@@ -16,29 +16,29 @@ const firebaseConfig = JSON.parse(serializedFirebaseConfig);
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
-self.addEventListener('install', () => {
- console.log('Service worker installed with Firebase config', firebaseConfig);
+self.addEventListener("install", () => {
+ console.log("Service worker installed with Firebase config", firebaseConfig);
self.skipWaiting();
});
-self.addEventListener('activate', (event) => {
+self.addEventListener("activate", (event) => {
event.waitUntil(self.clients.claim());
});
-self.addEventListener('fetch', (event) => {
+self.addEventListener("fetch", (event) => {
const { origin, pathname } = new URL(event.request.url);
if (origin !== self.location.origin) return;
// Use a magic url to ensure that auth state is in sync between
// the client and the sw, this helps with actions such as router.refresh();
- if (pathname.startsWith('/__/auth/wait/')) {
- const uid = pathname.split('/').at(-1);
+ if (pathname.startsWith("/__/auth/wait/")) {
+ const uid = pathname.split("/").at(-1);
event.respondWith(waitForMatchingUid(uid));
return;
}
- if (pathname.startsWith('/_next/')) return;
+ if (pathname.startsWith("/_next/")) return;
// Don't add headers to non-get requests or those with an extension—this
// helps with css, images, fonts, json, etc.
- if (event.request.method === 'GET' && pathname.includes('.')) return;
+ if (event.request.method === "GET" && pathname.includes(".")) return;
event.respondWith(fetchWithFirebaseHeaders(event.request));
});
@@ -46,20 +46,20 @@ async function fetchWithFirebaseHeaders(request) {
const authIdToken = await getAuthIdToken();
if (authIdToken) {
const headers = new Headers(request.headers);
- headers.append('Authorization', `Bearer ${authIdToken}`);
+ headers.append("Authorization", `Bearer ${authIdToken}`);
request = new Request(request, { headers });
}
return await fetch(request).catch((reason) => {
console.error(reason);
- return new Response('Fail.', {
+ return new Response("Fail.", {
status: 500,
- headers: { 'content-type': 'text/html' },
+ headers: { "content-type": "text/html" },
});
});
}
async function waitForMatchingUid(_uid) {
- const uid = _uid === 'undefined' ? undefined : _uid;
+ const uid = _uid === "undefined" ? undefined : _uid;
await auth.authStateReady();
await new Promise((resolve) => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
@@ -71,7 +71,7 @@ async function waitForMatchingUid(_uid) {
});
return new Response(undefined, {
status: 200,
- headers: { 'cache-control': 'no-store' },
+ headers: { "cache-control": "no-store" },
});
}
diff --git a/nextjs-end/src/app/actions.js b/nextjs-end/src/app/actions.js
index dee55aee..79cc8a61 100644
--- a/nextjs-end/src/app/actions.js
+++ b/nextjs-end/src/app/actions.js
@@ -1,8 +1,8 @@
-'use server';
+"use server";
-import { addReviewToRestaurant } from '@/src/lib/firebase/firestore.js';
-import { getAuthenticatedAppForUser } from '@/src/lib/firebase/serverApp.js';
-import { getFirestore } from 'firebase/firestore';
+import { addReviewToRestaurant } from "@/src/lib/firebase/firestore.js";
+import { getAuthenticatedAppForUser } from "@/src/lib/firebase/serverApp.js";
+import { getFirestore } from "firebase/firestore";
// This is a Server Action
// https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions
@@ -10,11 +10,11 @@ export async function handleReviewFormSubmission(data) {
const { firebaseServerApp } = await getAuthenticatedAppForUser();
const db = getFirestore(firebaseServerApp);
- await addReviewToRestaurant(db, data.get('restaurantId'), {
- text: data.get('text'),
- rating: data.get('rating'),
+ await addReviewToRestaurant(db, data.get("restaurantId"), {
+ text: data.get("text"),
+ rating: data.get("rating"),
// This came from a hidden form field
- userId: data.get('userId'),
+ userId: data.get("userId"),
});
}
diff --git a/nextjs-end/src/app/layout.js b/nextjs-end/src/app/layout.js
index 6604e904..dad6ea92 100644
--- a/nextjs-end/src/app/layout.js
+++ b/nextjs-end/src/app/layout.js
@@ -1,20 +1,20 @@
-import '@/src/app/styles.css';
-import Header from '@/src/components/Header.jsx';
-import { getAuthenticatedAppForUser } from '@/src/lib/firebase/serverApp';
+import "@/src/app/styles.css";
+import Header from "@/src/components/Header.jsx";
+import { getAuthenticatedAppForUser } from "@/src/lib/firebase/serverApp";
// Force next.js to treat this route as server-side rendered
// Without this line, during the build process, next.js will treat this route as static and build a static HTML file for it
-export const dynamic = 'force-dynamic';
+export const dynamic = "force-dynamic";
export const metadata = {
- title: 'FriendlyEats',
+ title: "FriendlyEats",
description:
- 'FriendlyEats is a restaurant review website built with Next.js and Firebase.',
+ "FriendlyEats is a restaurant review website built with Next.js and Firebase.",
};
export default async function RootLayout({ children }) {
const { currentUser } = await getAuthenticatedAppForUser();
return (
-
+
diff --git a/nextjs-end/src/app/page.js b/nextjs-end/src/app/page.js
index f092e885..e07647f3 100644
--- a/nextjs-end/src/app/page.js
+++ b/nextjs-end/src/app/page.js
@@ -1,12 +1,12 @@
-import RestaurantListings from '@/src/components/RestaurantListings.jsx';
-import { getRestaurants } from '@/src/lib/firebase/firestore.js';
-import { getAuthenticatedAppForUser } from '@/src/lib/firebase/serverApp.js';
-import { getFirestore } from 'firebase/firestore';
+import RestaurantListings from "@/src/components/RestaurantListings.jsx";
+import { getRestaurants } from "@/src/lib/firebase/firestore.js";
+import { getAuthenticatedAppForUser } from "@/src/lib/firebase/serverApp.js";
+import { getFirestore } from "firebase/firestore";
// Force next.js to treat this route as server-side rendered
// Without this line, during the build process, next.js will treat this route as static and build a static HTML file for it
-export const dynamic = 'force-dynamic';
+export const dynamic = "force-dynamic";
// This line also forces this route to be server-side rendered
// export const revalidate = 0;
@@ -20,7 +20,7 @@ export default async function Home({ searchParams }) {
searchParams,
);
return (
-
+ {
diff --git a/nextjs-end/src/app/restaurant/[id]/page.jsx b/nextjs-end/src/app/restaurant/[id]/page.jsx
index 0ab46dfc..d8e16acf 100644
--- a/nextjs-end/src/app/restaurant/[id]/page.jsx
+++ b/nextjs-end/src/app/restaurant/[id]/page.jsx
@@ -1,18 +1,18 @@
-import Restaurant from '@/src/components/Restaurant.jsx';
-import { Suspense } from 'react';
-import { getRestaurantById } from '@/src/lib/firebase/firestore.js';
+import Restaurant from "@/src/components/Restaurant.jsx";
+import { Suspense } from "react";
+import { getRestaurantById } from "@/src/lib/firebase/firestore.js";
import {
getAuthenticatedAppForUser,
getAuthenticatedAppForUser as getUser,
-} from '@/src/lib/firebase/serverApp.js';
+} from "@/src/lib/firebase/serverApp.js";
import ReviewsList, {
ReviewsListSkeleton,
-} from '@/src/components/Reviews/ReviewsList';
+} from "@/src/components/Reviews/ReviewsList";
import {
GeminiSummary,
GeminiSummarySkeleton,
-} from '@/src/components/Reviews/ReviewSummary';
-import { getFirestore } from 'firebase/firestore';
+} from "@/src/components/Reviews/ReviewSummary";
+import { getFirestore } from "firebase/firestore";
export default async function Home({ params }) {
const { currentUser } = await getUser();
@@ -23,11 +23,11 @@ export default async function Home({ params }) {
);
return (
-
+ }>
@@ -36,7 +36,7 @@ export default async function Home({ params }) {
}
>
-
+
);
diff --git a/nextjs-end/src/app/styles.css b/nextjs-end/src/app/styles.css
index d4036677..b9584b99 100644
--- a/nextjs-end/src/app/styles.css
+++ b/nextjs-end/src/app/styles.css
@@ -1,4 +1,4 @@
-@import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,500;0,700;1,800&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap');
+@import url("https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,500;0,700;1,800&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap");
* {
box-sizing: border-box;
@@ -8,7 +8,7 @@
body {
font-family:
- 'Roboto',
+ "Roboto",
ui-sans-serif,
system-ui,
-apple-system;
@@ -289,9 +289,9 @@ a {
}
.restaurant__review_summary {
- max-width: '50vw';
- height: '75px';
- padding-top: '10px';
+ max-width: "50vw";
+ height: "75px";
+ padding-top: "10px";
}
.img__section {
@@ -419,7 +419,7 @@ a {
}
.radio-label:before {
- content: '★';
+ content: "★";
display: inline-block;
font-size: 32px;
}
@@ -454,7 +454,7 @@ a {
.average-rating::before {
--percent: calc(4.3 / 5 * 100%);
- content: '★★★★★';
+ content: "★★★★★";
position: absolute;
top: 0;
left: 0;
diff --git a/nextjs-end/src/components/Filters.jsx b/nextjs-end/src/components/Filters.jsx
index 985dcca2..515e7961 100644
--- a/nextjs-end/src/components/Filters.jsx
+++ b/nextjs-end/src/components/Filters.jsx
@@ -1,6 +1,6 @@
// The filters shown on the restaurant listings page
-import Tag from '@/src/components/Tag.jsx';
+import Tag from "@/src/components/Tag.jsx";
function FilterSelect({ label, options, value, onChange, name, icon }) {
return (
@@ -11,7 +11,7 @@ function FilterSelect({ label, options, value, onChange, name, icon }) {
@@ -33,104 +33,104 @@ export default function Filters({ filters, setFilters }) {
};
return (
-
-
+
+
-
+
Restaurants
-
Sorted by {filters.sort || 'Rating'}
+
Sorted by {filters.sort || "Rating"}
-
+
{Object.entries(filters).map(([type, value]) => {
// The main filter bar already specifies what
// sorting is being used. So skip showing the
// sorting as a 'tag'
- if (type == 'sort' || value == '') {
+ if (type == "sort" || value == "") {
return null;
}
return (
diff --git a/nextjs-end/src/components/Header.jsx b/nextjs-end/src/components/Header.jsx
index 880f414f..76dd4c04 100644
--- a/nextjs-end/src/components/Header.jsx
+++ b/nextjs-end/src/components/Header.jsx
@@ -1,14 +1,14 @@
-'use client';
-import React, { useState, useEffect } from 'react';
-import Link from 'next/link';
+"use client";
+import React, { useState, useEffect } from "react";
+import Link from "next/link";
import {
signInWithGoogle,
signOut,
onAuthStateChanged,
-} from '@/src/lib/firebase/auth.js';
-import { addFakeRestaurantsAndReviews } from '@/src/lib/firebase/firestore.js';
-import { useRouter } from 'next/navigation';
-import { firebaseConfig } from '@/src/lib/firebase/config';
+} from "@/src/lib/firebase/auth.js";
+import { addFakeRestaurantsAndReviews } from "@/src/lib/firebase/firestore.js";
+import { useRouter } from "next/navigation";
+import { firebaseConfig } from "@/src/lib/firebase/config";
function useUserSession(initialUser) {
// The initialUser comes from the server via a server component
@@ -18,16 +18,16 @@ function useUserSession(initialUser) {
// Register the service worker that sends auth state back to server
// The service worker is built with npm run build-service-worker
useEffect(() => {
- if ('serviceWorker' in navigator) {
+ if ("serviceWorker" in navigator) {
const serializedFirebaseConfig = encodeURIComponent(
JSON.stringify(firebaseConfig),
);
const serviceWorkerUrl = `/auth-service-worker.js?firebaseConfig=${serializedFirebaseConfig}`;
navigator.serviceWorker
- .register(serviceWorkerUrl, { scope: '/', updateViaCache: 'none' })
+ .register(serviceWorkerUrl, { scope: "/", updateViaCache: "none" })
.then((registration) => {
- console.log('scope is: ', registration.scope);
+ console.log("scope is: ", registration.scope);
registration.update();
});
}
@@ -38,9 +38,9 @@ function useUserSession(initialUser) {
if (user?.uid === authUser?.uid) {
return;
}
- if ('serviceWorker' in navigator) {
+ if ("serviceWorker" in navigator) {
await navigator.serviceWorker.ready;
- await fetch(`/__/auth/wait/${authUser?.uid}`, { method: 'HEAD' }).catch(
+ await fetch(`/__/auth/wait/${authUser?.uid}`, { method: "HEAD" }).catch(
() => undefined,
);
}
@@ -67,35 +67,35 @@ export default function Header({ initialUser }) {
return (
-
-
+
+
Friendly Eats
{user ? (
<>
-
diff --git a/nextjs-end/src/components/RestaurantListings.jsx b/nextjs-end/src/components/RestaurantListings.jsx
index 270d721b..d17f1ec7 100644
--- a/nextjs-end/src/components/RestaurantListings.jsx
+++ b/nextjs-end/src/components/RestaurantListings.jsx
@@ -1,14 +1,14 @@
-'use client';
+"use client";
// This components handles the restaurant listings page
// It receives data from src/app/page.jsx, such as the initial restaurants and search params from the URL
-import Link from 'next/link';
-import { React, useState, useEffect } from 'react';
-import { useRouter } from 'next/navigation';
-import renderStars from '@/src/components/Stars.jsx';
-import { getRestaurantsSnapshot } from '@/src/lib/firebase/firestore.js';
-import Filters from '@/src/components/Filters.jsx';
+import Link from "next/link";
+import { React, useState, useEffect } from "react";
+import { useRouter } from "next/navigation";
+import renderStars from "@/src/components/Stars.jsx";
+import { getRestaurantsSnapshot } from "@/src/lib/firebase/firestore.js";
+import Filters from "@/src/components/Filters.jsx";
const RestaurantItem = ({ restaurant }) => (