Firebase را با برنامه Next.js ادغام کنید

1. قبل از شروع

در این کد لبه، یاد خواهید گرفت که چگونه Firebase را با یک برنامه وب Next.js به نام Friendly Eats که یک وب سایت برای بررسی رستوران ها است، ادغام کنید.

برنامه وب Friendly Eats

برنامه وب تکمیل شده ویژگی های مفیدی را ارائه می دهد که نشان می دهد Firebase چگونه می تواند به شما در ساخت برنامه های Next.js کمک کند. این ویژگی ها شامل موارد زیر است:

  • ساخت و استقرار خودکار: این کد لبه از میزبانی برنامه Firebase برای ساخت و استقرار خودکار کد Next.js شما هر بار که به یک شاخه پیکربندی شده فشار می‌دهید، استفاده می‌کند.
  • ورود و خروج: برنامه وب تکمیل شده به شما امکان می دهد با Google وارد شوید و از سیستم خارج شوید. ورود و تداوم کاربر به طور کامل از طریق Firebase Authentication مدیریت می شود.
  • تصاویر: برنامه وب تکمیل شده به کاربرانی که وارد سیستم شده اند اجازه می دهد تصاویر رستوران را آپلود کنند. دارایی های تصویر در Cloud Storage برای Firebase ذخیره می شوند. Firebase JavaScript SDK یک URL عمومی برای تصاویر آپلود شده فراهم می کند. سپس این URL عمومی در سند رستوران مربوطه در Cloud Firestore ذخیره می‌شود.
  • نظرات: برنامه وب تکمیل‌شده به کاربرانی که وارد سیستم شده‌اند اجازه می‌دهد نظرات رستوران‌هایی را که شامل رتبه‌بندی ستاره و پیام متنی هستند، ارسال کنند. اطلاعات مرور در Cloud Firestore ذخیره می شود.
  • فیلترها: برنامه وب تکمیل‌شده به کاربرانی که وارد سیستم شده‌اند اجازه می‌دهد فهرست رستوران‌ها را بر اساس دسته، مکان و قیمت فیلتر کنند. همچنین می توانید روش مرتب سازی مورد استفاده را سفارشی کنید. داده ها از Cloud Firestore قابل دسترسی هستند و پرس و جوهای Firestore بر اساس فیلترهای استفاده شده اعمال می شوند.

پیش نیازها

  • یک حساب GitHub
  • آشنایی با Next.js و جاوا اسکریپت

چیزی که یاد خواهید گرفت

  • نحوه استفاده از Firebase با روتر برنامه Next.js و رندر سمت سرور.
  • نحوه ماندگاری تصاویر در Cloud Storage برای Firebase.
  • نحوه خواندن و نوشتن داده ها در پایگاه داده Cloud Firestore.
  • نحوه استفاده از ورود به سیستم با Google با Firebase JavaScript SDK.

آنچه شما نیاز دارید

  • Git
  • نسخه پایدار اخیر Node.js
  • مرورگر دلخواه شما، مانند گوگل کروم
  • یک محیط توسعه با ویرایشگر کد و ترمینال
  • یک حساب Google برای ایجاد و مدیریت پروژه Firebase شما
  • توانایی ارتقاء پروژه Firebase خود به طرح قیمت گذاری Blaze

2. محیط توسعه و مخزن GitHub خود را راه اندازی کنید

این لبه کد پایه کد شروع برنامه را فراهم می کند و به Firebase CLI متکی است.

یک مخزن GitHub ایجاد کنید

منبع Codelab را می توان در https://github.com/firebase/friendlyeats-web یافت. این مخزن شامل پروژه های نمونه برای چندین پلتفرم است. با این حال، این کد لبه فقط از دایرکتوری nextjs-start استفاده می کند. به دایرکتوری های زیر توجه کنید:

* `nextjs-start`: contains the starter code upon which you build.
* `nextjs-end`: contains the solution code for the finished web app.

پوشه nextjs-start را در مخزن خود کپی کنید:

  1. با استفاده از یک ترمینال، یک پوشه جدید در رایانه خود ایجاد کنید و به دایرکتوری جدید تغییر دهید:
    mkdir codelab-friendlyeats-web
    
    cd codelab-friendlyeats-web
    
  2. از بسته giget npm برای واکشی فقط پوشه nextjs-start استفاده کنید:
    npx giget@latest gh:firebase/friendlyeats-web/nextjs-start#master . --install
    
  3. ردیابی تغییرات به صورت محلی با git:
    git init
    
    git commit -a -m "codelab starting point"
    
    git branch -M main
    
  4. یک مخزن جدید GitHub ایجاد کنید: https://github.com/new . اسمش رو هر چی دوست داری بذار
    1. GitHub یک URL مخزن جدید به شما می دهد که شبیه به https://github.com/ / .git است. https://github.com/ / .git https://github.com/ / .git یا [email protected]: / .git [email protected]: / .git [email protected]: / .git . این URL را کپی کنید.
  5. تغییرات محلی را به مخزن جدید GitHub خود فشار دهید. دستور زیر را اجرا کنید و URL مخزن خود را جایگزین کنید نگهدارنده مکان
    git remote add origin <your-repository-url>
    
    git push -u origin main
    
  6. اکنون باید کد شروع را در مخزن GitHub خود مشاهده کنید.

Firebase CLI را نصب یا به‌روزرسانی کنید

برای بررسی اینکه Firebase CLI را نصب کرده اید و نسخه 13.9.0 یا بالاتر است، دستور زیر را اجرا کنید:

firebase --version

اگر نسخه پایین‌تری می‌بینید یا Firebase CLI را نصب نکرده‌اید، دستور install را اجرا کنید:

npm install -g firebase-tools@latest

اگر به دلیل خطاهای مجوز نمی توانید Firebase CLI را نصب کنید، اسناد npm را ببینید یا از گزینه نصب دیگری استفاده کنید.

وارد Firebase شوید

  1. برای ورود به Firebase CLI دستور زیر را اجرا کنید:
    firebase login
    
  2. بسته به اینکه می خواهید Firebase داده ها را جمع آوری کند، Y یا N را وارد کنید.
  3. در مرورگر خود، حساب Google خود را انتخاب کنید و سپس روی Allow کلیک کنید.

3. پروژه Firebase خود را راه اندازی کنید

در این بخش، یک پروژه Firebase را راه‌اندازی کرده و یک برنامه وب Firebase را با آن مرتبط می‌کنید. همچنین سرویس‌های Firebase را که توسط برنامه وب نمونه استفاده می‌شود، راه‌اندازی می‌کنید.

یک پروژه Firebase ایجاد کنید

  1. در کنسول Firebase ، روی افزودن پروژه کلیک کنید.
  2. در کادر متنی نام پروژه خود را وارد کنید ، FriendlyEats Codelab (یا نام پروژه دلخواهتان) را وارد کنید و سپس روی Continue کلیک کنید.
  3. در حالت تأیید طرح صورت‌حساب Firebase ، تأیید کنید که طرح Blaze است و سپس روی تأیید طرح کلیک کنید
  4. برای این کد لبه، شما نیازی به Google Analytics ندارید، بنابراین گزینه Enable Google Analytics for this project را غیرفعال کنید.
  5. روی ایجاد پروژه کلیک کنید.
  6. منتظر بمانید تا پروژه شما ارائه شود و سپس روی Continue کلیک کنید.
  7. در پروژه Firebase خود، به تنظیمات پروژه بروید. شناسه پروژه خود را یادداشت کنید زیرا بعداً به آن نیاز دارید. این شناسه منحصر به فرد نحوه شناسایی پروژه شما است (به عنوان مثال، در Firebase CLI).

طرح قیمت گذاری Firebase خود را ارتقا دهید

برای استفاده از میزبانی برنامه، پروژه Firebase شما باید در طرح قیمت‌گذاری Blaze باشد، به این معنی که با حساب صورت‌حساب Cloud مرتبط است.

  • حساب Cloud Billing به یک روش پرداخت مانند کارت اعتباری نیاز دارد.
  • اگر تازه وارد Firebase و Google Cloud هستید، بررسی کنید که آیا واجد شرایط دریافت اعتبار 300 دلاری و یک حساب آزمایشی رایگان Cloud Billing هستید یا خیر.

برای ارتقای پروژه خود به پلن Blaze، مراحل زیر را دنبال کنید:

  1. در کنسول Firebase، برنامه خود را ارتقا دهید.
  2. در گفتگو، طرح Blaze را انتخاب کنید، و سپس دستورالعمل های روی صفحه را دنبال کنید تا پروژه خود را با یک حساب Cloud Billing مرتبط کنید.
    اگر نیاز به ایجاد حساب Cloud Billing داشتید، ممکن است لازم باشد برای تکمیل ارتقا به جریان ارتقا در کنسول Firebase برگردید.

یک برنامه وب به پروژه Firebase خود اضافه کنید

  1. در پروژه Firebase خود به نمای کلی پروژه خود بروید و سپس کلیک کنید e41f2efdd9539c31.png وب

    اگر قبلاً برنامه‌هایی را در پروژه خود ثبت کرده‌اید، روی افزودن برنامه کلیک کنید تا نماد وب را ببینید.
  2. در کادر متنی نام مستعار برنامه ، یک نام مستعار برنامه به یاد ماندنی، مانند My Next.js app وارد کنید.
  3. چک باکس همچنین تنظیم Firebase Hosting برای این برنامه را بدون علامت نگه دارید.
  4. روی ثبت برنامه > بعدی > بعدی > ادامه به کنسول کلیک کنید.

سرویس های Firebase را در کنسول Firebase تنظیم کنید

احراز هویت را تنظیم کنید

  1. در کنسول Firebase، به Authentication بروید.
  2. روی Get start کلیک کنید.
  3. در ستون ارائه دهندگان اضافی ، روی Google > فعال کردن کلیک کنید.
  4. در کادر متنی نام عمومی برای پروژه ، یک نام به یاد ماندنی مانند My Next.js app وارد کنید.
  5. از ایمیل کشویی پشتیبانی برای پروژه ، آدرس ایمیل خود را انتخاب کنید.
  6. روی ذخیره کلیک کنید.

Cloud Firestore را راه اندازی کنید

  1. در کنسول Firebase، به Firestore بروید.
  2. روی ایجاد پایگاه داده > بعدی > شروع در حالت آزمایشی > بعدی کلیک کنید.
    بعداً در این لبه کد، قوانین امنیتی را برای ایمن کردن اطلاعات خود اضافه خواهید کرد. بدون افزودن قوانین امنیتی برای پایگاه داده خود، یک برنامه را به صورت عمومی توزیع یا افشا نکنید .
  3. از مکان پیش فرض استفاده کنید یا مکان مورد نظر خود را انتخاب کنید.
    برای یک برنامه واقعی، می خواهید مکانی را انتخاب کنید که به کاربران شما نزدیک باشد. توجه داشته باشید که این مکان بعداً قابل تغییر نیست و همچنین به طور خودکار مکان سطل ذخیره سازی ابری پیش فرض شما خواهد بود (مرحله بعدی).
  4. روی Done کلیک کنید.

Cloud Storage را برای Firebase تنظیم کنید

  1. در کنسول Firebase، به Storage بروید.
  2. روی شروع > شروع در حالت آزمایش > بعدی کلیک کنید.
    بعداً در این کد، قوانین امنیتی را برای ایمن سازی داده های خود اضافه خواهید کرد. بدون افزودن قوانین امنیتی برای سطل ذخیره‌سازی خود ، برنامه‌ای را به صورت عمومی توزیع یا افشا نکنید .
  3. محل سطل شما باید از قبل انتخاب شده باشد (به دلیل راه اندازی Firestore در مرحله قبل).
  4. روی Done کلیک کنید.

4. پایگاه کد استارتر را مرور کنید

در این بخش، چند قسمت از پایگاه کد شروع برنامه را بررسی می‌کنید که عملکردی را در این لبه کد به آن‌ها اضافه می‌کنید.

ساختار پوشه و فایل

جدول زیر شامل نمای کلی از پوشه و ساختار فایل برنامه است:

پوشه ها و فایل ها

توضیحات

src/components

برای فیلترها، سرصفحه‌ها، جزئیات رستوران و نظرات، اجزای سازنده واکنش نشان دهید

src/lib

توابع ابزاری که لزوماً به React یا Next.js مقید نیستند

src/lib/firebase

کد مخصوص Firebase و پیکربندی Firebase

public

دارایی های ثابت در برنامه وب، مانند نمادها

src/app

مسیریابی با روتر برنامه Next.js

src/app/restaurant

یک کنترل کننده مسیر API

package.json و package-lock.json

وابستگی های پروژه با npm

next.config.js

پیکربندی ویژه Next.js (عملکردهای سرور فعال هستند)

jsconfig.json

پیکربندی سرویس زبان جاوا اسکریپت

اجزای سرور و مشتری

این برنامه یک برنامه وب Next.js است که از App Router استفاده می کند. رندر سرور در سراسر برنامه استفاده می شود. به عنوان مثال، فایل src/app/page.js یک جزء سرور مسئول صفحه اصلی است. فایل src/components/RestaurantListings.jsx یک جزء سرویس گیرنده است که با دستور "use client" در ابتدای فایل مشخص شده است.

بیانیه های وارداتی

ممکن است متوجه عبارات وارداتی مانند زیر شوید:

import RatingPicker from "@/src/components/RatingPicker.jsx";

این برنامه از نماد @ استفاده می کند تا از مسیرهای وارداتی نسبی بی نظم جلوگیری کند و با نام مستعار مسیر امکان پذیر است.

API های مخصوص Firebase

تمام کدهای Firebase API در پوشه src/lib/firebase پیچیده شده است. سپس اجزای React فردی، توابع پیچیده شده را از دایرکتوری src/lib/firebase وارد می کنند، نه اینکه توابع Firebase را مستقیما وارد کنند.

داده های ساختگی

اطلاعات تقلبی رستوران و بررسی در فایل src/lib/randomData.js موجود است. داده های آن فایل در کد موجود در فایل src/lib/fakeRestaurants.js جمع آوری می شود.

5. یک باطن میزبانی برنامه ایجاد کنید

در این بخش، یک App Hosting Backend را برای تماشای یک شعبه در مخزن git خود راه اندازی خواهید کرد.

در پایان این بخش، یک باطن میزبانی برنامه خواهید داشت که به مخزن خود در GitHub متصل است که هر زمان که یک commit جدید را به شعبه main خود فشار دهید، به طور خودکار نسخه جدیدی از برنامه شما را بازسازی و عرضه می کند.

استقرار قوانین امنیتی

این کد قبلاً دارای مجموعه‌ای از قوانین امنیتی برای Firestore و برای Cloud Storage برای Firebase است. پس از استقرار قوانین امنیتی، داده های پایگاه داده و سطل شما بهتر از سوء استفاده محافظت می شوند.

  1. در ترمینال خود، CLI را برای استفاده از پروژه Firebase که قبلا ایجاد کردید، پیکربندی کنید:
    firebase use --add
    
    وقتی نام مستعار از شما خواسته شد، friendlyeats-codelab وارد کنید.
  2. برای استقرار این قوانین امنیتی، این دستور را در ترمینال خود اجرا کنید:
    firebase deploy --only firestore:rules,storage
    
  3. اگر از شما پرسیده شود: "Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?" ، Enter فشار دهید تا Yes را انتخاب کنید.

پیکربندی Firebase خود را به کد برنامه وب خود اضافه کنید

  1. در کنسول Firebase، به تنظیمات پروژه خود بروید.
  2. در قسمت تنظیمات و پیکربندی SDK ، روی «افزودن برنامه» کلیک کنید و روی نماد براکت کد کلیک کنید. برای ثبت یک برنامه وب جدید
  3. در پایان جریان ایجاد برنامه وب، متغیر firebaseConfig را کپی کنید و خواص و مقادیر آن را کپی کنید.
  4. فایل apphosting.yaml را در ویرایشگر کد خود باز کنید و مقادیر متغیر محیطی را با مقادیر پیکربندی کنسول Firebase پر کنید.
  5. در فایل، ویژگی های موجود را با مواردی که کپی کرده اید جایگزین کنید.
  6. فایل را ذخیره کنید.

یک Backend ایجاد کنید

  1. به صفحه میزبانی برنامه در کنسول Firebase بروید:

حالت صفر کنسول میزبان برنامه، با دکمه «شروع به کار».

  1. برای شروع جریان ایجاد backend روی «شروع به کار» کلیک کنید. باطن خود را به صورت زیر پیکربندی کنید:
  2. برای اتصال مخزن GitHub که قبلا ایجاد کردید، دستورات مرحله اول را دنبال کنید.
  3. تنظیم تنظیمات استقرار:
    1. دایرکتوری ریشه را به صورت / نگه دارید
    2. شاخه زنده را روی main قرار دهید
    3. فعال کردن عرضه خودکار
  4. باطن خود را friendlyeats-codelab نام ببرید.
  5. در «ایجاد یا مرتبط کردن یک برنامه وب Firebase»، برنامه وب را که قبلاً پیکربندی کرده‌اید از منوی کشویی «انتخاب یک برنامه وب Firebase موجود» انتخاب کنید.
  6. روی "Finish and Deploy" کلیک کنید. پس از مدتی، به صفحه جدیدی هدایت خواهید شد که در آن می‌توانید وضعیت باطن میزبانی برنامه جدید خود را ببینید!
  7. پس از تکمیل عرضه، روی دامنه رایگان خود در زیر «دامنه ها» کلیک کنید. به دلیل انتشار DNS ممکن است چند دقیقه طول بکشد تا شروع به کار کند.

شما برنامه وب اولیه را مستقر کرده اید! هر بار که یک commit جدید را به شاخه main مخزن GitHub خود فشار می دهید، می بینید که یک ساخت و عرضه جدید در کنسول Firebase شروع می شود و سایت شما به طور خودکار پس از تکمیل عرضه به روز می شود.

6. احراز هویت را به برنامه وب اضافه کنید

در این بخش، احراز هویت را به وب اپلیکیشن اضافه می کنید تا بتوانید وارد آن شوید.

عملکردهای ورود و خروج را پیاده سازی کنید

  1. در فایل src/lib/firebase/auth.js ، توابع onAuthStateChanged ، signInWithGoogle و signOut را با کد زیر جایگزین کنید:
export function onAuthStateChanged(cb) {
	return _onAuthStateChanged(auth, cb);
}

export async function signInWithGoogle() {
  const provider = new GoogleAuthProvider();

  try {
    await signInWithPopup(auth, provider);
  } catch (error) {
    console.error("Error signing in with Google", error);
  }
}

export async function signOut() {
  try {
    return auth.signOut();
  } catch (error) {
    console.error("Error signing out with Google", error);
  }
}

این کد از API های Firebase زیر استفاده می کند:

Firebase API

توضیحات

GoogleAuthProvider

یک نمونه ارائه دهنده احراز هویت Google ایجاد می کند.

signInWithPopup

یک جریان احراز هویت مبتنی بر گفتگو را شروع می کند.

auth.signOut

کاربر را از سیستم خارج می کند.

در فایل src/components/Header.jsx ، کد از قبل توابع signInWithGoogle و signOut فراخوانی می کند.

  1. یک commit با پیام commit "Adding Google Authentication" ایجاد کنید و آن را به مخزن GitHub خود فشار دهید. 1. صفحه میزبانی برنامه را در کنسول Firebase باز کنید و منتظر بمانید تا عرضه جدید خود را تکمیل کنید.
  2. در برنامه وب، صفحه را بازخوانی کنید و روی Sign in with Google کلیک کنید. برنامه وب به‌روزرسانی نمی‌شود، بنابراین مشخص نیست که آیا ورود به سیستم با موفقیت انجام شد یا خیر.

وضعیت احراز هویت را به سرور ارسال کنید

برای انتقال وضعیت احراز هویت به سرور، از یک سرویس‌کار استفاده می‌کنیم. توابع fetchWithFirebaseHeaders و getAuthIdToken را با کد زیر جایگزین کنید:

async function fetchWithFirebaseHeaders(request) {
  const app = initializeApp(firebaseConfig);
  const auth = getAuth(app);
  const installations = getInstallations(app);
  const headers = new Headers(request.headers);
  const [authIdToken, installationToken] = await Promise.all([
    getAuthIdToken(auth),
    getToken(installations),
  ]);
  headers.append("Firebase-Instance-ID-Token", installationToken);
  if (authIdToken) headers.append("Authorization", `Bearer ${authIdToken}`);
  const newRequest = new Request(request, { headers });
  return await fetch(newRequest);
}

async function getAuthIdToken(auth) {
  await auth.authStateReady();
  if (!auth.currentUser) return;
  return await getIdToken(auth.currentUser);
}

وضعیت احراز هویت را در سرور بخوانید

ما از FirebaseServerApp برای منعکس کردن وضعیت احراز هویت مشتری در سرور استفاده خواهیم کرد.

src/lib/firebase/serverApp.js را باز کنید و تابع getAuthenticatedAppForUser را جایگزین کنید:

export async function getAuthenticatedAppForUser() {
  const idToken = headers().get("Authorization")?.split("Bearer ")[1];
  console.log('firebaseConfig', JSON.stringify(firebaseConfig));
  const firebaseServerApp = initializeServerApp(
    firebaseConfig,
    idToken
      ? {
          authIdToken: idToken,
        }
      : {}
  );

  const auth = getAuth(firebaseServerApp);
  await auth.authStateReady();

  return { firebaseServerApp, currentUser: auth.currentUser };
}

در تغییرات احراز هویت مشترک شوید

برای اشتراک در تغییرات احراز هویت، مراحل زیر را دنبال کنید:

  1. به فایل src/components/Header.jsx بروید.
  2. تابع useUserSession را با کد زیر جایگزین کنید:
function useUserSession(initialUser) {
	// The initialUser comes from the server via a server component
	const [user, setUser] = useState(initialUser);
	const router = useRouter();

	// 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) {
			const serializedFirebaseConfig = encodeURIComponent(JSON.stringify(firebaseConfig));
			const serviceWorkerUrl = `/auth-service-worker.js?firebaseConfig=${serializedFirebaseConfig}`
		
		  navigator.serviceWorker
			.register(serviceWorkerUrl)
			.then((registration) => console.log("scope is: ", registration.scope));
		}
	  }, []);

	useEffect(() => {
		const unsubscribe = onAuthStateChanged((authUser) => {
			setUser(authUser)
		})

		return () => unsubscribe()
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, []);

	useEffect(() => {
		onAuthStateChanged((authUser) => {
			if (user === undefined) return

			// refresh when user changed to ease testing
			if (user?.email !== authUser?.email) {
				router.refresh()
			}
		})
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [user])

	return user;
}

زمانی که تابع onAuthStateChanged مشخص می کند که تغییری در وضعیت احراز هویت وجود دارد، این کد از یک قلاب وضعیت React برای به روز رسانی کاربر استفاده می کند.

تغییرات را تأیید کنید

طرح‌بندی ریشه در فایل src/app/layout.js هدر را رندر می‌کند و در صورت موجود بودن، به‌عنوان پایه به کاربر منتقل می‌کند.

<Header initialUser={currentUser?.toJSON()} />

این بدان معناست که مؤلفه <Header> داده‌های کاربر را، در صورت وجود، در طول زمان اجرای سرور ارائه می‌کند. اگر در طول چرخه حیات صفحه پس از بارگیری اولیه صفحه، به‌روزرسانی‌هایی برای احراز هویت وجود داشته باشد، کنترل‌کننده onAuthStateChanged آنها را مدیریت می‌کند.

اکنون وقت آن است که یک بیلد جدید راه اندازی کنید و آنچه را که ساخته اید تأیید کنید.

  1. یک commit با پیام commit "Show signin state" ایجاد کنید و آن را به مخزن GitHub خود فشار دهید.
  2. صفحه میزبانی برنامه را در کنسول Firebase باز کنید و منتظر بمانید تا عرضه جدید شما تکمیل شود.
  3. رفتار احراز هویت جدید را تأیید کنید:
    1. در مرورگر خود، برنامه وب را بازخوانی کنید. نام نمایشی شما در هدر ظاهر می شود.
    2. از سیستم خارج شوید و دوباره وارد شوید. صفحه در زمان واقعی و بدون رفرش صفحه به روز می شود. می توانید این مرحله را با کاربران مختلف تکرار کنید.
    3. اختیاری: روی برنامه وب کلیک راست کنید، View page source را انتخاب کنید و نام نمایشی را جستجو کنید. در منبع HTML خام که از سرور بازگردانده شده است ظاهر می شود.

7. مشاهده اطلاعات رستوران

برنامه وب شامل داده های ساختگی برای رستوران ها و نظرات است.

یک یا چند رستوران اضافه کنید

برای درج داده های رستوران ساختگی در پایگاه داده محلی Cloud Firestore خود، این مراحل را دنبال کنید:

  1. در برنامه وب، را انتخاب کنید 2cf67d488d8e6332.png > رستوران های نمونه را اضافه کنید .
  2. در کنسول Firebase در صفحه پایگاه داده Firestore ، رستوران ها را انتخاب کنید. اسناد سطح بالا را در مجموعه رستوران مشاهده می کنید که هر کدام نشان دهنده یک رستوران هستند.
  3. برای بررسی ویژگی‌های یک سند رستوران، روی چند سند کلیک کنید.

نمایش لیست رستوران ها

پایگاه داده Cloud Firestore شما اکنون رستوران هایی دارد که برنامه وب Next.js می تواند نمایش دهد.

برای تعریف کد واکشی داده، مراحل زیر را دنبال کنید:

  1. در فایل src/app/page.js ، مؤلفه سرور <Home /> را بیابید و تماس تابع getRestaurants را بررسی کنید، که لیستی از رستوران ها را در زمان اجرای سرور بازیابی می کند. تابع getRestaurants را در مراحل زیر پیاده سازی می کنید.
  2. در فایل src/lib/firebase/firestore.js ، توابع applyQueryFilters و getRestaurants را با کد زیر جایگزین کنید:
function applyQueryFilters(q, { category, city, price, sort }) {
	if (category) {
		q = query(q, where("category", "==", category));
	}
	if (city) {
		q = query(q, where("city", "==", city));
	}
	if (price) {
		q = query(q, where("price", "==", price.length));
	}
	if (sort === "Rating" || !sort) {
		q = query(q, orderBy("avgRating", "desc"));
	} else if (sort === "Review") {
		q = query(q, orderBy("numRatings", "desc"));
	}
	return q;
}

export async function getRestaurants(db = db, filters = {}) {
	let q = query(collection(db, "restaurants"));

	q = applyQueryFilters(q, filters);
	const results = await getDocs(q);
	return results.docs.map(doc => {
		return {
			id: doc.id,
			...doc.data(),
			// Only plain objects can be passed to Client Components from Server Components
			timestamp: doc.data().timestamp.toDate(),
		};
	});
}
  1. یک commit با پیام commit "خواندن لیست رستوران ها از Firestore" ایجاد کنید و آن را به مخزن GitHub خود فشار دهید.
  2. صفحه میزبانی برنامه را در کنسول Firebase باز کنید و منتظر بمانید تا عرضه جدید شما تکمیل شود.
  3. در برنامه وب، صفحه را بازخوانی کنید. تصاویر رستوران به صورت کاشی در صفحه ظاهر می شوند.

بررسی کنید که لیست رستوران ها در زمان اجرای سرور بارگیری می شوند

با استفاده از چارچوب Next.js، زمانی که داده ها در زمان اجرای سرور یا زمان اجرای سمت کلاینت بارگیری می شوند، ممکن است واضح نباشد.

برای تأیید بارگیری فهرست‌های رستوران در زمان اجرای سرور، این مراحل را دنبال کنید:

  1. در برنامه وب، DevTools را باز کنید و جاوا اسکریپت را غیرفعال کنید .

JavaScipt را در DevTools غیرفعال کنید

  1. برنامه وب را بازخوانی کنید. لیست رستوران ها هنوز بارگیری می شود. اطلاعات رستوران در پاسخ سرور برگردانده می شود. وقتی جاوا اسکریپت فعال است، اطلاعات رستوران از طریق کد جاوا اسکریپت سمت سرویس گیرنده هیدراته می شود.
  2. در DevTools، جاوا اسکریپت را دوباره فعال کنید .

با شنوندگان عکس فوری Cloud Firestore به به‌روزرسانی‌های رستوران گوش دهید

در بخش قبل، نحوه بارگیری مجموعه اولیه رستوران ها از فایل src/app/page.js را مشاهده کردید. فایل src/app/page.js یک جزء سرور است و بر روی سرور ارائه می شود، از جمله کد واکشی داده Firebase.

فایل src/components/RestaurantListings.jsx یک جزء سرویس گیرنده است و می تواند برای هیدراته کردن نشانه گذاری ارائه شده توسط سرور پیکربندی شود.

برای پیکربندی فایل src/components/RestaurantListings.jsx برای هیدراته کردن نشانه‌گذاری ارائه‌شده توسط سرور، این مراحل را دنبال کنید:

  1. در فایل src/components/RestaurantListings.jsx کد زیر را که قبلا برای شما نوشته شده است رعایت کنید:
useEffect(() => {
        const unsubscribe = getRestaurantsSnapshot(data => {
                setRestaurants(data);
        }, filters);

        return () => {
                unsubscribe();
        };
}, [filters]);

این کد تابع getRestaurantsSnapshot() را فراخوانی می کند که شبیه تابع getRestaurants() است که در مرحله قبل پیاده سازی کردید. با این حال، این تابع عکس فوری یک مکانیسم تماس را فراهم می کند به طوری که هر بار که تغییری در مجموعه رستوران ایجاد می شود، پاسخ تماس فراخوانی می شود.

  1. در فایل src/lib/firebase/firestore.js ، تابع getRestaurantsSnapshot() را با کد زیر جایگزین کنید:
export function getRestaurantsSnapshot(cb, filters = {}) {
	if (typeof cb !== "function") {
		console.log("Error: The callback parameter is not a function");
		return;
	}

	let q = query(collection(db, "restaurants"));
	q = applyQueryFilters(q, filters);

	const unsubscribe = onSnapshot(q, querySnapshot => {
		const results = querySnapshot.docs.map(doc => {
			return {
				id: doc.id,
				...doc.data(),
				// Only plain objects can be passed to Client Components from Server Components
				timestamp: doc.data().timestamp.toDate(),
			};
		});

		cb(results);
	});

	return unsubscribe;
}

تغییرات ایجاد شده از طریق صفحه پایگاه داده Firestore اکنون در برنامه وب در زمان واقعی منعکس می شود.

  1. یک commit با پیام commit "Listen for realtime restaurant updates" ایجاد کنید و آن را به مخزن GitHub خود فشار دهید.
  2. صفحه میزبانی برنامه را در کنسول Firebase باز کنید و منتظر بمانید تا عرضه جدید شما تکمیل شود.
  3. در برنامه وب، را انتخاب کنید 27ca5d1e8ed8adfe.png > رستوران های نمونه را اضافه کنید . اگر عملکرد عکس فوری شما به درستی اجرا شود، رستوران‌ها در زمان واقعی و بدون بازخوانی صفحه ظاهر می‌شوند.

8. نظرات ارسال شده توسط کاربر را از برنامه وب ذخیره کنید

  1. در فایل src/lib/firebase/firestore.js ، تابع updateWithRating() را با کد زیر جایگزین کنید:
const updateWithRating = async (
	transaction,
	docRef,
	newRatingDocument,
	review
) => {
	const restaurant = await transaction.get(docRef);
	const data = restaurant.data();
	const newNumRatings = data?.numRatings ? data.numRatings + 1 : 1;
	const newSumRating = (data?.sumRating || 0) + Number(review.rating);
	const newAverage = newSumRating / newNumRatings;

	transaction.update(docRef, {
		numRatings: newNumRatings,
		sumRating: newSumRating,
		avgRating: newAverage,
	});

	transaction.set(newRatingDocument, {
		...review,
		timestamp: Timestamp.fromDate(new Date()),
	});
};

این کد یک سند Firestore جدید را وارد می کند که نمایانگر بررسی جدید است. این کد همچنین سند Firestore موجود را به روز می کند که نشان دهنده رستوران با ارقام به روز شده برای تعداد رتبه بندی ها و میانگین امتیاز محاسبه شده است.

  1. تابع addReviewToRestaurant() را با کد زیر جایگزین کنید:
export async function addReviewToRestaurant(db, restaurantId, review) {
	if (!restaurantId) {
		throw new Error("No restaurant ID has been provided.");
	}

	if (!review) {
		throw new Error("A valid review has not been provided.");
	}

	try {
		const docRef = doc(collection(db, "restaurants"), restaurantId);
		const newRatingDocument = doc(
			collection(db, `restaurants/${restaurantId}/ratings`)
		);

		// corrected line
		await runTransaction(db, transaction =>
			updateWithRating(transaction, docRef, newRatingDocument, review)
		);
	} catch (error) {
		console.error(
			"There was an error adding the rating to the restaurant",
			error
		);
		throw error;
	}
}

یک اکشن سرور Next.js را اجرا کنید

یک Next.js Server Action یک API مناسب برای دسترسی به داده‌های فرم، مانند data.get("text") برای دریافت مقدار متن از بار ارسال فرم ارائه می‌کند.

برای استفاده از Next.js Server Action برای پردازش ارسال فرم بررسی، مراحل زیر را دنبال کنید:

  1. در فایل src/components/ReviewDialog.jsx ، ویژگی action را در عنصر <form> پیدا کنید.
<form action={handleReviewFormSubmission}>

مقدار مشخصه action به تابعی اشاره دارد که در مرحله بعد پیاده سازی می کنید.

  1. در فایل src/app/actions.js ، تابع handleReviewFormSubmission() را با کد زیر جایگزین کنید:
// This is a next.js server action, which is an alpha feature, so
// use with caution.
// https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions
export async function handleReviewFormSubmission(data) {
        const { app } = await getAuthenticatedAppForUser();
        const db = getFirestore(app);

        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"),
        });
}

نظرات را برای یک رستوران اضافه کنید

شما از ارسال‌های نقد پشتیبانی کردید، بنابراین اکنون می‌توانید بررسی کنید که نظرات شما به درستی در Cloud Firestore درج شده است.

برای افزودن نظر و تأیید اینکه در Cloud Firestore درج شده است، این مراحل را دنبال کنید:

  1. یک commit با پیام commit "اجازه به کاربران برای ارسال نظرات رستوران" ایجاد کنید و آن را به مخزن GitHub خود فشار دهید.
  2. صفحه میزبانی برنامه را در کنسول Firebase باز کنید و منتظر بمانید تا عرضه جدید شما تکمیل شود.
  3. برنامه وب را بازخوانی کنید و یک رستوران را از صفحه اصلی انتخاب کنید.
  4. در صفحه رستوران کلیک کنید 3e19beef78bb0d0e.png .
  5. رتبه بندی ستاره را انتخاب کنید.
  6. یک بررسی بنویسید.
  7. روی ارسال کلیک کنید. نظر شما در بالای لیست نظرات ظاهر می شود.
  8. در Cloud Firestore، در پنجره افزودن سند ، سند رستورانی را که بررسی کرده‌اید جستجو کنید و آن را انتخاب کنید.
  9. در صفحه مجموعه شروع ، رتبه بندی ها را انتخاب کنید.
  10. در صفحه افزودن سند ، سندی را برای بررسی خود پیدا کنید تا تأیید کنید که مطابق انتظار درج شده است.

اسناد در شبیه ساز Firestore

9. فایل های آپلود شده توسط کاربر را از برنامه وب ذخیره کنید

در این بخش، عملکردی را اضافه می‌کنید تا بتوانید هنگام ورود به سیستم، تصویر مرتبط با یک رستوران را جایگزین کنید. تصویر را در Firebase Storage آپلود می‌کنید و URL تصویر را در سند Cloud Firestore که نشان‌دهنده رستوران است، به‌روزرسانی می‌کنید.

برای ذخیره فایل‌های آپلود شده توسط کاربر از برنامه وب، این مراحل را دنبال کنید:

  1. در فایل src/components/Restaurant.jsx ، کدی را که هنگام آپلود فایل توسط کاربر اجرا می‌شود، مشاهده کنید:
async function handleRestaurantImage(target) {
        const image = target.files ? target.files[0] : null;
        if (!image) {
                return;
        }

        const imageURL = await updateRestaurantImage(id, image);
        setRestaurant({ ...restaurant, photo: imageURL });
}

هیچ تغییری لازم نیست، اما شما رفتار تابع updateRestaurantImage() را در مراحل زیر پیاده سازی می کنید.

  1. در فایل src/lib/firebase/storage.js ، توابع updateRestaurantImage() و uploadImage() را با کد زیر جایگزین کنید:
export async function updateRestaurantImage(restaurantId, image) {
	try {
		if (!restaurantId)
			throw new Error("No restaurant ID has been provided.");

		if (!image || !image.name)
			throw new Error("A valid image has not been provided.");

		const publicImageUrl = await uploadImage(restaurantId, image);
		await updateRestaurantImageReference(restaurantId, publicImageUrl);

		return publicImageUrl;
	} catch (error) {
		console.error("Error processing request:", error);
	}
}

async function uploadImage(restaurantId, image) {
	const filePath = `images/${restaurantId}/${image.name}`;
	const newImageRef = ref(storage, filePath);
	await uploadBytesResumable(newImageRef, image);

	return await getDownloadURL(newImageRef);
}

تابع updateRestaurantImageReference() قبلاً برای شما پیاده سازی شده است. این تابع یک سند رستوران موجود در Cloud Firestore را با URL تصویر به روز شده به روز می کند.

عملکرد آپلود تصویر را تأیید کنید

برای تأیید اینکه تصویر طبق انتظار آپلود می شود، این مراحل را دنبال کنید:

  1. یک commit با پیام commit "اجازه به کاربران برای تغییر عکس هر رستوران" ایجاد کنید و آن را به مخزن GitHub خود فشار دهید.
  2. صفحه میزبانی برنامه را در کنسول Firebase باز کنید و منتظر بمانید تا عرضه جدید شما تکمیل شود.
  3. در برنامه وب، تأیید کنید که وارد سیستم شده اید و یک رستوران را انتخاب کنید.
  4. کلیک کنید 7067eb41fea41ff0.png و یک تصویر از فایل سیستم خود آپلود کنید. تصویر شما از محیط محلی شما خارج می شود و در فضای ذخیره سازی ابری آپلود می شود. تصویر بلافاصله پس از آپلود ظاهر می شود.
  5. برای Firebase به Cloud Storage بروید.
  6. به پوشه ای که نشان دهنده رستوران است بروید. تصویری که آپلود کردید در پوشه وجود دارد.

6cf3f9e2303c931c.png

10. نظرات رستوران را با مولد ai خلاصه کنید

در این بخش، ویژگی خلاصه بررسی را اضافه می‌کنید تا کاربر بتواند بدون نیاز به خواندن هر نظر، به سرعت بفهمد که همه درباره یک رستوران چه فکر می‌کنند.

یک کلید API Gemini را در Cloud Secret Manager ذخیره کنید

  1. برای استفاده از Gemini API، به یک کلید API نیاز دارید. یک کلید در Google AI Studio ایجاد کنید .
  2. میزبانی برنامه با Cloud Secret Manager ادغام می شود تا به شما امکان می دهد مقادیر حساس مانند کلیدهای API را به صورت ایمن ذخیره کنید:
    1. در یک ترمینال، دستور ایجاد یک راز جدید را اجرا کنید:
    firebase apphosting:secrets:set gemini-api-key
    
    1. هنگامی که مقدار مخفی از شما خواسته شد، کلید Gemini API خود را از Google AI Studio کپی و جایگذاری کنید.
    2. وقتی از شما پرسیده شد که آیا راز جدید باید به apphosting.yaml اضافه شود، Y وارد کنید تا بپذیرید.

کلید Gemini API شما اکنون به طور ایمن در مدیر Cloud Secret ذخیره می‌شود و برای میزبانی برنامه شما قابل دسترسی است.

مولفه خلاصه بررسی را پیاده سازی کنید

  1. در src/components/Reviews/ReviewSummary.jsx ، تابع GeminiSummary را با کد زیر جایگزین کنید:
    export async function GeminiSummary({ restaurantId }) {
        const { firebaseServerApp } = await getAuthenticatedAppForUser();
        const reviews = await getReviewsByRestaurantId(
            getFirestore(firebaseServerApp),
            restaurantId
        );
    
        const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
        const model = genAI.getGenerativeModel({ model: "gemini-pro"});
    
        const reviewSeparator = "@";
        const prompt = `
            Based on the following restaurant reviews, 
            where each review is separated by a '${reviewSeparator}' character, 
            create a one-sentence summary of what people think of the restaurant. 
    
            Here are the reviews: ${reviews.map(review => review.text).join(reviewSeparator)}
        `;
    
        try {
            const result = await model.generateContent(prompt);
            const response = await result.response;
            const text = response.text();
    
            return (
                <div className="restaurant__review_summary">
                    <p>{text}</p>
                    <p> Summarized with Gemini</p>
                </div>
            );
        } catch (e) {
            console.error(e);
            return <p>Error contacting Gemini</p>;
        }
    }
    
  2. یک commit با پیام commit "استفاده از هوش مصنوعی برای خلاصه کردن نظرات" ایجاد کنید و آن را به مخزن GitHub خود فشار دهید.
  3. صفحه میزبانی برنامه را در کنسول Firebase باز کنید و منتظر بمانید تا عرضه جدید شما تکمیل شود.
  4. یک صفحه برای رستوران باز کنید. در بالا، باید خلاصه‌ای از تمام نظرات موجود در صفحه را یک جمله ببینید.
  5. یک بررسی جدید اضافه کنید و صفحه را بازخوانی کنید. شما باید تغییر خلاصه را ببینید.

11. نتیجه گیری

تبریک می گویم! یاد گرفتید که چگونه از Firebase برای افزودن ویژگی‌ها و عملکرد به برنامه Next.js استفاده کنید. به طور خاص از موارد زیر استفاده کردید:

بیشتر بدانید