فصل یازدهم: گسترش اپلیکیشن
در این فصل، به گسترش اپلیکیشن مرکز اجاره کشتیهای کروز با افزودن ویژگیهای پیشرفته میپردازیم. این ویژگیها شامل احراز هویت با استفاده از @sidebase/nuxt-auth، اتصال به پایگاه داده با Supabase یا Prisma، پرداخت آنلاین با Stripe، و تحلیل دادهها با @nuxtjs/plausible است. این قابلیتها اپلیکیشن را به یک محصول کامل و آماده برای استفاده تجاری تبدیل میکنند. هر بخش بهطور کامل توضیح داده شده و مراحل پیادهسازی شرح داده میشوند.
احراز هویت (Authentication)
برای افزودن احراز هویت به اپلیکیشن، از ماژول @sidebase/nuxt-auth استفاده میکنیم که یک راهحل مدرن و ساده برای پیادهسازی OAuth یا JWT در Nuxt 3 ارائه میدهد.
مراحل پیادهسازی:
- نصب ماژول:
npm install @sidebase/nuxt-auth
- بهروزرسانی
nuxt.config.ts:
export default defineNuxtConfig({
modules: ['@pinia/nuxt', '@nuxtjs/tailwindcss', '@nuxt/image', '@nuxt/content', '@sidebase/nuxt-auth'],
auth: {
provider: {
type: 'authjs',
trustHost: true,
defaultProvider: 'github', // یا Google، Auth0 و غیره
},
},
});
-
ایجاد فایل تنظیمات Auth.js:
-
فایل
server/api/auth/[...].tsرا برای مدیریت مسیرهای احراز هویت ایجاد کنید:
// server/api/auth/[...].ts
import { NuxtAuthHandler } from '#auth';
import GithubProvider from 'next-auth/providers/github';
export default NuxtAuthHandler({
providers: [
GithubProvider({
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
}),
],
});
-
تنظیم متغیرهای محیطی:
-
در فایل
.env، کلیدهای OAuth را اضافه کنید:
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
-
بهروزرسانی میدلور:
-
میدلور احراز هویت (
middleware/auth.ts) را برای استفاده از@sidebase/nuxt-authبهروزرسانی کنید:
// middleware/auth.ts
import { useAuth } from '#auth';
export default defineNuxtRouteMiddleware(async (to) => {
const { status } = useAuth();
if (to.path === '/bookings' && status.value !== 'authenticated') {
return navigateTo('/login');
}
});
-
ایجاد صفحه ورود:
-
فایل
pages/login.vueرا برای ورود کاربران ایجاد کنید:
<!-- pages/login.vue -->
<template>
<div class="container mx-auto p-6">
<h1 class="text-3xl font-bold mb-6">Login</h1>
<button @click="signInWithGithub" class="btn">Sign in with GitHub</button>
</div>
</template>
<script setup>
import { signIn } from '#auth';
const signInWithGithub = async () => {
await signIn('github', { callbackUrl: '/bookings' });
};
</script>
توضیحات:
- ماژول
@sidebase/nuxt-auth: از Auth.js (NextAuth) برای مدیریت احراز هویت استفاده میکند و با Nuxt 3 ادغام شده است. - ارائهدهندهها: در این مثال، از GitHub بهعنوان ارائهدهنده OAuth استفاده شده است، اما میتوان از Google، Auth0 یا JWT استفاده کرد.
- میدلور: بررسی میکند که آیا کاربر احراز هویت شده است یا خیر و در صورت لزوم به صفحه ورود هدایت میکند.
- کاربرد: این سیستم احراز هویت دسترسی به صفحه رزروها (
/bookings) را محدود میکند و تجربه کاربری ایمنتری فراهم میکند. -
مزایا:
-
پشتیبانی از چندین ارائهدهنده OAuth.
- ادغام ساده با Nuxt 3 و موتور Nitro.
- مدیریت خودکار سشنها و توکنها.
اتصال به پایگاه داده (Database)
برای ذخیرهسازی دائمی دادهها (مانند کشتیها و رزروها)، میتوان از Supabase (پایگاه داده ابری مبتنی بر PostgreSQL) یا Prisma (ORM برای پایگاه دادههای مختلف) استفاده کرد.
گزینه ۱: ادغام با Supabase
- نصب ماژول:
npm install @nuxtjs/supabase
- بهروزرسانی
nuxt.config.ts:
export default defineNuxtConfig({
modules: ['@pinia/nuxt', '@nuxtjs/tailwindcss', '@nuxt/image', '@nuxt/content', '@sidebase/nuxt-auth', '@nuxtjs/supabase'],
supabase: {
url: process.env.SUPABASE_URL,
key: process.env.SUPABASE_KEY,
},
});
- تنظیم متغیرهای محیطی:
SUPABASE_URL=your-supabase-url
SUPABASE_KEY=your-supabase-key
-
بهروزرسانی مسیرهای سرور:
-
مسیر
/api/shipsرا برای دریافت دادهها از Supabase بهروزرسانی کنید:
// server/api/ships.ts
import { serverSupabaseClient } from '#supabase/server';
import type { Ship } from '~/types';
export default defineEventHandler(async (event): Promise<Ship[]> => {
const client = serverSupabaseClient(event);
const { data } = await client.from('ships').select('*');
return data || [];
});
- مسیر
/api/bookingsرا برای مدیریت رزروها بهروزرسانی کنید:
// server/api/bookings.ts
import { serverSupabaseClient } from '#supabase/server';
import type { Booking } from '~/types';
export default defineEventHandler({
async get(event) {
const client = serverSupabaseClient(event);
const { data } = await client.from('bookings').select('*');
return data || [];
},
async post(event) {
const client = serverSupabaseClient(event);
const body = await readBody(event);
const newBooking: Booking = {
id: Date.now(), // در تولید از UUID استفاده کنید
shipId: body.shipId,
startDate: new Date(body.startDate),
endDate: new Date(body.endDate),
totalPrice: body.totalPrice,
};
const { data } = await client.from('bookings').insert(newBooking).select();
return data[0];
},
});
-
ایجاد جداول در Supabase:
-
در داشبورد Supabase، دو جدول ایجاد کنید:
- جدول
ships: با ستونهایid,name,capacity,pricePerDay,amenities,image. - جدول
bookings: با ستونهایid,shipId,startDate,endDate,totalPrice.
- جدول
گزینه ۲: ادغام با Prisma
- نصب Prisma:
npm install prisma @prisma/client
npx prisma init
- تنظیم فایل
prisma/schema.prisma:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Ship {
id Int @id @default(autoincrement())
name String
capacity Int
pricePerDay Int
amenities String[]
image String
bookings Booking[]
}
model Booking {
id Int @id @default(autoincrement())
shipId Int
startDate DateTime
endDate DateTime
totalPrice Int
ship Ship @relation(fields: [shipId], references: [id])
}
-
بهروزرسانی مسیرهای سرور:
-
مشابه Supabase، مسیرهای
/api/shipsو/api/bookingsرا برای استفاده از Prisma بهروزرسانی کنید:
// server/api/ships.ts
import { PrismaClient } from '@prisma/client';
import type { Ship } from '~/types';
const prisma = new PrismaClient();
export default defineEventHandler(async (): Promise<Ship[]> => {
return prisma.ship.findMany();
});
توضیحات:
- Supabase: یک پایگاه داده ابری با API ساده و ادغام مستقیم با Nuxt از طریق
@nuxtjs/supabase. مناسب برای پروژههای کوچک تا متوسط. - Prisma: یک ORM قدرتمند که با پایگاه دادههای مختلف (مانند PostgreSQL، MySQL) کار میکند و برای پروژههای پیچیدهتر مناسب است.
- کاربرد: این ادغامها جایگزین ذخیرهسازی موقت در حافظه (مانند آرایه
bookingsدر فصل ششم) میشوند و دادهها را بهصورت دائمی ذخیره میکنند. -
مزایا:
-
مقیاسپذیری و پایداری دادهها.
- پشتیبانی از پرسوجوهای پیچیده.
- ادغام آسان با Nuxt.
پرداخت آنلاین (Payments)
برای افزودن قابلیت پرداخت به رزروها، از Stripe استفاده میکنیم که یک پلتفرم پرداخت امن و قابل اعتماد است.
مراحل پیادهسازی:
- نصب Stripe:
npm install @stripe/stripe-js stripe
-
ایجاد مسیر سرور برای پرداخت:
-
فایل
server/api/stripe-checkout.tsرا ایجاد کنید:
// server/api/stripe-checkout.ts
import Stripe from 'stripe';
import type { Booking } from '~/types';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, { apiVersion: '2024-06-20' });
export default defineEventHandler(async (event) => {
const body = await readBody(event);
const booking: Booking = body.booking;
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: [
{
price_data: {
currency: 'usd',
product_data: { name: `Booking for Ship ${booking.shipId}` },
unit_amount: booking.totalPrice * 100, // Stripe از سنت استفاده میکند
},
quantity: 1,
},
],
mode: 'payment',
success_url: `${useRuntimeConfig().public.appUrl}/bookings?success=true`,
cancel_url: `${useRuntimeConfig().public.appUrl}/bookings?canceled=true`,
});
return { id: session.id };
});
- بهروزرسانی
nuxt.config.ts:
export default defineNuxtConfig({
runtimeConfig: {
public: {
appUrl: process.env.APP_URL || 'http://localhost:3000',
stripePublishableKey: process.env.STRIPE_PUBLISHABLE_KEY,
},
stripeSecretKey: process.env.STRIPE_SECRET_KEY,
},
});
- بهروزرسانی فرم رزرو در
pages/ships/[id].vue:
<script setup>
import { loadStripe } from '@stripe/stripe-js';
const submit = handleSubmit(async (values) => {
if (!ship.value) return;
const days = (new Date(values.endDate) - new Date(values.startDate)) / (1000 * 60 * 60 * 24);
const totalPrice = days * ship.value.pricePerDay;
const booking = {
shipId: ship.value.id,
startDate: new Date(values.startDate),
endDate: new Date(values.endDate),
totalPrice,
};
const { id } = await $fetch('/api/stripe-checkout', {
method: 'POST',
body: { booking },
});
const stripe = await loadStripe(useRuntimeConfig().public.stripePublishableKey);
await stripe.redirectToCheckout({ sessionId: id });
await bookingsStore.addBooking(booking);
alert('Booking successful!');
form.startDate = '';
form.endDate = '';
});
</script>
- تنظیم متغیرهای محیطی:
STRIPE_PUBLISHABLE_KEY=your-stripe-publishable-key
STRIPE_SECRET_KEY=your-stripe-secret-key
APP_URL=https://your-app-url.com
توضیحات:
- Stripe: امکان پردازش پرداختهای آنلاین را فراهم میکند.
- مسیر سرور: یک جلسه پرداخت (Checkout Session) در Stripe ایجاد میکند و کاربران را به صفحه پرداخت هدایت میکند.
- فرم رزرو: پس از اعتبارسنجی فرم، یک درخواست به مسیر Stripe ارسال میشود و کاربر به صفحه پرداخت Stripe هدایت میشود.
-
مزایا:
-
امنیت بالا با استانداردهای PCI.
- پشتیبانی از پرداختهای بینالمللی.
- تجربه کاربری ساده با ریدایرکت به صفحه پرداخت.
تحلیل دادهها (Analytics)
برای ردیابی رفتار کاربران و تحلیل عملکرد اپلیکیشن، از Plausible Analytics با ماژول @nuxtjs/plausible استفاده میکنیم.
مراحل پیادهسازی:
- نصب ماژول:
npm install @nuxtjs/plausible
- بهروزرسانی
nuxt.config.ts:
export default defineNuxtConfig({
modules: ['@pinia/nuxt', '@nuxtjs/tailwindcss', '@nuxt/image', '@nuxt/content', '@sidebase/nuxt-auth', '@nuxtjs/supabase', '@nuxtjs/plausible'],
plausible: {
domain: 'your-app-url.com',
apiHost: 'https://plausible.io', // یا سرور خودهاستشده
},
});
-
تنظیم متغیرهای محیطی:
-
اگر از Plausible خودهاستشده استفاده میکنید، متغیر
PLAUSIBLE_API_HOSTرا در.envاضافه کنید:
PLAUSIBLE_API_HOST=https://your-plausible-host.com
-
ردیابی رویدادهای سفارشی:
-
برای ردیابی رزروهای موفق، در
pages/ships/[id].vueیک رویداد به Plausible ارسال کنید:
import { usePlausible } from '#plausible';
const plausible = usePlausible();
const submit = handleSubmit(async (values) => {
// ... کد پرداخت و رزرو
plausible('Booking Completed', { props: { shipId: ship.value.id, totalPrice } });
});
توضیحات:
- Plausible Analytics: یک ابزار تحلیل سبک و متمرکز بر حریم خصوصی که جایگزین Google Analytics است.
- ماژول
@nuxtjs/plausible: ردیابی خودکار بازدیدهای صفحه و رویدادهای سفارشی را فراهم میکند. - کاربرد: ردیابی رزروها، بازدید صفحات، یا اقدامات کاربر (مانند کلیک روی دکمهها).
-
مزایا:
-
سبک و بدون کوکی، مناسب برای قوانین حریم خصوصی (مانند GDPR).
- ادغام ساده با Nuxt.
- امکان ردیابی رویدادهای سفارشی.
جمعبندی فصل یازدهم
در این فصل، اپلیکیشن مرکز اجاره کشتیهای کروز را با افزودن ویژگیهای پیشرفته گسترش دادیم:
- احراز هویت: با
@sidebase/nuxt-authبرای محدود کردن دسترسی به صفحات حساس. - پایگاه داده: با Supabase یا Prisma برای ذخیرهسازی دائمی دادهها.
- پرداخت آنلاین: با Stripe برای پردازش پرداخت رزروها.
- تحلیل دادهها: با
@nuxtjs/plausibleبرای ردیابی رفتار کاربران.
این ویژگیها اپلیکیشن را به یک محصول کامل و حرفهای تبدیل میکنند که آماده استفاده تجاری است. با این حال، میتوانید با افزودن قابلیتهایی مانند محلیسازی، اعلانها، یا داشبوردهای مدیریتی، اپلیکیشن را بیشتر بهبود دهید.