feat(plugin): pirogue-providers (Phase 3.3)
Modèle PirogueProvider (id, name, contacts, fleuves, tarif, description) + enum TransportMode (OWNER_PROVIDES, SELF_ARRANGE, PARTNER_PROVIDER) sur Carbet + relation Carbet → PirogueProvider (nullable, ondelete:SetNull) Composants : - PirogueTransportBlock (server, gated par plugin) sur fiche carbet : affiche le mode + provider partenaire avec contacts/tarif/description - Page publique /partenaires-pirogue : liste des partenaires actifs Seed onEnable : - 3 partenaires démo (Pirogues du Maroni, Approuague Aventures, Oyapock Frontière) avec tarifs estimatifs et fleuves desservis réels - Attribution aux 6 carbets démo : · Awara (Maroni), Maripa (Approuague), Paripou (Oyapock) → PARTNER_PROVIDER · Wapa (Comté), Mahury CE → OWNER_PROVIDES · Kourou Couleuvre → SELF_ARRANGE onDisable désactive les partenaires démo et détache les carbets démo.
This commit is contained in:
parent
8c0b849ad7
commit
a174f99eba
9 changed files with 438 additions and 7 deletions
|
|
@ -0,0 +1,29 @@
|
|||
-- Plugin pirogue-providers : modèle PirogueProvider + transportMode sur Carbet
|
||||
|
||||
CREATE TYPE "TransportMode" AS ENUM ('OWNER_PROVIDES', 'SELF_ARRANGE', 'PARTNER_PROVIDER');
|
||||
|
||||
CREATE TABLE "PirogueProvider" (
|
||||
"id" TEXT PRIMARY KEY,
|
||||
"name" TEXT NOT NULL,
|
||||
"contactEmail" TEXT,
|
||||
"contactPhone" TEXT,
|
||||
"rivers" TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[],
|
||||
"pricingNote" TEXT,
|
||||
"description" TEXT,
|
||||
"active" BOOLEAN NOT NULL DEFAULT true,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX "PirogueProvider_active_idx" ON "PirogueProvider" ("active");
|
||||
|
||||
ALTER TABLE "Carbet"
|
||||
ADD COLUMN "transportMode" "TransportMode",
|
||||
ADD COLUMN "pirogueProviderId" TEXT;
|
||||
|
||||
ALTER TABLE "Carbet"
|
||||
ADD CONSTRAINT "Carbet_pirogueProviderId_fkey"
|
||||
FOREIGN KEY ("pirogueProviderId") REFERENCES "PirogueProvider"("id")
|
||||
ON DELETE SET NULL;
|
||||
|
||||
CREATE INDEX "Carbet_pirogueProviderId_idx" ON "Carbet" ("pirogueProviderId");
|
||||
|
|
@ -64,6 +64,12 @@ enum AccessType {
|
|||
RIVER_ONLY
|
||||
}
|
||||
|
||||
enum TransportMode {
|
||||
OWNER_PROVIDES
|
||||
SELF_ARRANGE
|
||||
PARTNER_PROVIDER
|
||||
}
|
||||
|
||||
model Organization {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
|
|
@ -125,23 +131,45 @@ model Carbet {
|
|||
// Contraintes saisonnières (plugin seasonality). JSON libre, schéma type :
|
||||
// { closedInLowWater: bool, closedSeasons: ["WET"|"DRY"|"LOW_WATER"][], note: string }
|
||||
seasonalConstraints Json?
|
||||
// Plugin pirogue-providers : qui organise le transport ?
|
||||
transportMode TransportMode?
|
||||
pirogueProviderId String?
|
||||
status CarbetStatus @default(DRAFT)
|
||||
lastBookedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
owner User @relation("CarbetOwner", fields: [ownerId], references: [id], onDelete: Restrict)
|
||||
amenities CarbetAmenity[]
|
||||
media Media[]
|
||||
availabilities Availability[]
|
||||
bookings Booking[]
|
||||
reviews Review[]
|
||||
owner User @relation("CarbetOwner", fields: [ownerId], references: [id], onDelete: Restrict)
|
||||
pirogueProvider PirogueProvider? @relation(fields: [pirogueProviderId], references: [id], onDelete: SetNull)
|
||||
amenities CarbetAmenity[]
|
||||
media Media[]
|
||||
availabilities Availability[]
|
||||
bookings Booking[]
|
||||
reviews Review[]
|
||||
subscriptions Subscription[]
|
||||
|
||||
@@index([ownerId])
|
||||
@@index([status])
|
||||
@@index([river])
|
||||
@@index([accessType])
|
||||
@@index([pirogueProviderId])
|
||||
}
|
||||
|
||||
model PirogueProvider {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
contactEmail String?
|
||||
contactPhone String?
|
||||
rivers String[] @default([])
|
||||
pricingNote String?
|
||||
description String?
|
||||
active Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
carbets Carbet[]
|
||||
|
||||
@@index([active])
|
||||
}
|
||||
|
||||
model Amenity {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import { ReviewsSection } from "../_components/reviews-section";
|
|||
import { StarRating } from "../_components/star-rating";
|
||||
import { AccessTypeBadge } from "@/components/AccessTypeBadge";
|
||||
import { StayConstraints } from "@/components/StayConstraints";
|
||||
import { PirogueTransportBlock } from "@/components/PirogueTransportBlock";
|
||||
|
||||
type PageProps = {
|
||||
params: Promise<{ slug: string }>;
|
||||
|
|
@ -137,6 +138,11 @@ export default async function PublicCarbetPage({ params }: PageProps) {
|
|||
</p>
|
||||
</section>
|
||||
|
||||
<PirogueTransportBlock
|
||||
transportMode={carbet.transportMode}
|
||||
provider={carbet.pirogueProvider}
|
||||
/>
|
||||
|
||||
{carbet.amenities.length > 0 ? (
|
||||
<section className="mt-10">
|
||||
<h2 className="text-xl font-semibold text-zinc-900">
|
||||
|
|
|
|||
88
src/app/partenaires-pirogue/page.tsx
Normal file
88
src/app/partenaires-pirogue/page.tsx
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
import { notFound } from "next/navigation";
|
||||
import { isPluginEnabled } from "@/lib/plugins/server";
|
||||
import { listActiveProviders } from "@/lib/pirogue-providers";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export async function generateMetadata() {
|
||||
return { title: "Partenaires pirogue" };
|
||||
}
|
||||
|
||||
export default async function ProvidersPage() {
|
||||
if (!(await isPluginEnabled("pirogue-providers"))) notFound();
|
||||
const providers = await listActiveProviders();
|
||||
|
||||
return (
|
||||
<main className="mx-auto max-w-4xl px-6 py-12 sm:px-8 lg:px-12">
|
||||
<header className="mb-8">
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.15em] text-[var(--color-karbe-canopy-700)]">
|
||||
Transport
|
||||
</span>
|
||||
<h1 className="mt-2 font-serif text-4xl font-medium tracking-tight text-[var(--color-karbe-ink)] sm:text-5xl">
|
||||
Nos partenaires pirogue
|
||||
</h1>
|
||||
<p className="mt-3 max-w-2xl text-base leading-relaxed text-[var(--color-karbe-ink)]/75">
|
||||
Pour les carbets accessibles uniquement par le fleuve, on travaille avec des piroguiers
|
||||
locaux référencés. Tarifs estimatifs ci-dessous ; le détail de votre trajet est calé
|
||||
directement avec le partenaire après réservation.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
{providers.length === 0 ? (
|
||||
<p className="rounded-xl border border-dashed border-[var(--color-karbe-canopy-100)] bg-[var(--color-karbe-canopy-50)]/40 p-6 text-sm text-[var(--color-karbe-ink)]/70">
|
||||
Aucun partenaire référencé pour le moment.
|
||||
</p>
|
||||
) : (
|
||||
<ul className="space-y-5">
|
||||
{providers.map((p) => (
|
||||
<li
|
||||
key={p.id}
|
||||
className="rounded-2xl border border-[var(--color-karbe-canopy-100)] bg-white p-6 shadow-sm"
|
||||
>
|
||||
<div className="flex flex-wrap items-baseline justify-between gap-3">
|
||||
<h2 className="font-serif text-2xl font-medium text-[var(--color-karbe-ink)]">{p.name}</h2>
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{p.rivers.map((r) => (
|
||||
<span
|
||||
key={r}
|
||||
className="rounded-full bg-[var(--color-karbe-maroni-100)] px-2 py-0.5 text-xs font-medium text-[var(--color-karbe-maroni-700)]"
|
||||
>
|
||||
{r}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
{p.description ? (
|
||||
<p className="mt-3 text-sm leading-relaxed text-[var(--color-karbe-ink)]/85">{p.description}</p>
|
||||
) : null}
|
||||
{p.pricingNote ? (
|
||||
<p className="mt-2 italic text-sm text-[var(--color-karbe-ink)]/70">{p.pricingNote}</p>
|
||||
) : null}
|
||||
<dl className="mt-4 flex flex-wrap gap-x-6 gap-y-1 text-xs">
|
||||
{p.contactEmail ? (
|
||||
<div>
|
||||
<dt className="inline font-semibold text-[var(--color-karbe-canopy-700)]">Email · </dt>
|
||||
<dd className="inline">
|
||||
<a
|
||||
href={`mailto:${p.contactEmail}`}
|
||||
className="underline hover:text-[var(--color-karbe-laterite-700)]"
|
||||
>
|
||||
{p.contactEmail}
|
||||
</a>
|
||||
</dd>
|
||||
</div>
|
||||
) : null}
|
||||
{p.contactPhone ? (
|
||||
<div>
|
||||
<dt className="inline font-semibold text-[var(--color-karbe-canopy-700)]">Tél. · </dt>
|
||||
<dd className="inline">{p.contactPhone}</dd>
|
||||
</div>
|
||||
) : null}
|
||||
</dl>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
80
src/components/PirogueTransportBlock.tsx
Normal file
80
src/components/PirogueTransportBlock.tsx
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
import { isPluginEnabled } from "@/lib/plugins/server";
|
||||
import {
|
||||
TRANSPORT_MODE_EMOJI,
|
||||
TRANSPORT_MODE_LABEL,
|
||||
type PirogueProvider,
|
||||
} from "@/lib/pirogue-providers";
|
||||
|
||||
/**
|
||||
* Bloc transport pirogue sur la fiche carbet (server component).
|
||||
* Gated par le plugin `pirogue-providers`. Sans le plugin, retourne null.
|
||||
*/
|
||||
export async function PirogueTransportBlock({
|
||||
transportMode,
|
||||
provider,
|
||||
}: {
|
||||
transportMode: string | null;
|
||||
provider: PirogueProvider | null;
|
||||
}) {
|
||||
if (!(await isPluginEnabled("pirogue-providers"))) return null;
|
||||
if (!transportMode) return null;
|
||||
|
||||
const emoji = TRANSPORT_MODE_EMOJI[transportMode] ?? "🛶";
|
||||
const label = TRANSPORT_MODE_LABEL[transportMode] ?? "Transport pirogue";
|
||||
|
||||
return (
|
||||
<section className="mt-8 rounded-2xl border border-[var(--color-karbe-canopy-100)] bg-[var(--color-karbe-canopy-50)]/40 p-6">
|
||||
<header className="flex items-center gap-2">
|
||||
<span aria-hidden className="text-2xl">{emoji}</span>
|
||||
<h2 className="font-serif text-xl font-medium text-[var(--color-karbe-ink)]">
|
||||
Transport pirogue — {label}
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
{transportMode === "PARTNER_PROVIDER" && provider ? (
|
||||
<div className="mt-4 space-y-2 text-sm leading-relaxed text-[var(--color-karbe-ink)]/85">
|
||||
<p>
|
||||
Ce carbet travaille avec un partenaire référencé :{" "}
|
||||
<strong className="text-[var(--color-karbe-canopy-700)]">{provider.name}</strong>
|
||||
</p>
|
||||
{provider.description ? <p>{provider.description}</p> : null}
|
||||
{provider.pricingNote ? (
|
||||
<p className="italic text-[var(--color-karbe-ink)]/70">{provider.pricingNote}</p>
|
||||
) : null}
|
||||
<dl className="mt-3 flex flex-wrap gap-x-6 gap-y-1 text-xs">
|
||||
{provider.contactEmail ? (
|
||||
<div>
|
||||
<dt className="inline font-semibold text-[var(--color-karbe-canopy-700)]">Email · </dt>
|
||||
<dd className="inline">
|
||||
<a
|
||||
href={`mailto:${provider.contactEmail}`}
|
||||
className="underline hover:text-[var(--color-karbe-laterite-700)]"
|
||||
>
|
||||
{provider.contactEmail}
|
||||
</a>
|
||||
</dd>
|
||||
</div>
|
||||
) : null}
|
||||
{provider.contactPhone ? (
|
||||
<div>
|
||||
<dt className="inline font-semibold text-[var(--color-karbe-canopy-700)]">Tél. · </dt>
|
||||
<dd className="inline">{provider.contactPhone}</dd>
|
||||
</div>
|
||||
) : null}
|
||||
</dl>
|
||||
</div>
|
||||
) : transportMode === "OWNER_PROVIDES" ? (
|
||||
<p className="mt-3 text-sm leading-relaxed text-[var(--color-karbe-ink)]/80">
|
||||
Le loueur s'occupe du transport : il vous récupère au point d'embarquement et
|
||||
vous ramène en fin de séjour. Détails de l'heure et du point de rendez-vous transmis
|
||||
par e-mail après réservation.
|
||||
</p>
|
||||
) : (
|
||||
<p className="mt-3 text-sm leading-relaxed text-[var(--color-karbe-ink)]/80">
|
||||
Le transport est à votre charge. Renseignez-vous auprès des piroguiers locaux du dégrad
|
||||
d'embarquement, ou prévenez-nous : on peut vous orienter vers un partenaire.
|
||||
</p>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
|
@ -2,12 +2,13 @@ import { cache } from "react";
|
|||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { amenityLabel } from "@/lib/amenities";
|
||||
import { AccessType, CarbetStatus, MediaType } from "@/generated/prisma/enums";
|
||||
import { AccessType, CarbetStatus, MediaType, TransportMode } from "@/generated/prisma/enums";
|
||||
import type { CarbetReview, CarbetReviewStats } from "@/lib/reviews";
|
||||
import {
|
||||
getCarbetReviewStats,
|
||||
listCarbetReviews,
|
||||
} from "@/lib/reviews-server";
|
||||
import type { PirogueProvider } from "@/lib/pirogue-providers";
|
||||
|
||||
export type PublicCarbetMedia = {
|
||||
id: string;
|
||||
|
|
@ -30,6 +31,8 @@ export type PublicCarbetDetail = {
|
|||
maxStayNights: number | null;
|
||||
minCapacity: number | null;
|
||||
seasonalConstraints: unknown;
|
||||
transportMode: TransportMode | null;
|
||||
pirogueProvider: PirogueProvider | null;
|
||||
latitude: string;
|
||||
longitude: string;
|
||||
ownerId: string;
|
||||
|
|
@ -61,10 +64,24 @@ export const getPublicCarbet = cache(
|
|||
maxStayNights: true,
|
||||
minCapacity: true,
|
||||
seasonalConstraints: true,
|
||||
transportMode: true,
|
||||
pirogueProviderId: true,
|
||||
latitude: true,
|
||||
longitude: true,
|
||||
ownerId: true,
|
||||
owner: { select: { firstName: true } },
|
||||
pirogueProvider: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
contactEmail: true,
|
||||
contactPhone: true,
|
||||
rivers: true,
|
||||
pricingNote: true,
|
||||
description: true,
|
||||
active: true,
|
||||
},
|
||||
},
|
||||
media: {
|
||||
orderBy: { sortOrder: "asc" },
|
||||
select: { id: true, type: true, s3Url: true },
|
||||
|
|
@ -97,6 +114,19 @@ export const getPublicCarbet = cache(
|
|||
maxStayNights: carbet.maxStayNights,
|
||||
minCapacity: carbet.minCapacity,
|
||||
seasonalConstraints: carbet.seasonalConstraints,
|
||||
transportMode: carbet.transportMode,
|
||||
pirogueProvider: carbet.pirogueProvider
|
||||
? {
|
||||
id: carbet.pirogueProvider.id,
|
||||
name: carbet.pirogueProvider.name,
|
||||
contactEmail: carbet.pirogueProvider.contactEmail,
|
||||
contactPhone: carbet.pirogueProvider.contactPhone,
|
||||
rivers: carbet.pirogueProvider.rivers,
|
||||
pricingNote: carbet.pirogueProvider.pricingNote,
|
||||
description: carbet.pirogueProvider.description,
|
||||
active: carbet.pirogueProvider.active,
|
||||
}
|
||||
: null,
|
||||
latitude: carbet.latitude.toString(),
|
||||
longitude: carbet.longitude.toString(),
|
||||
ownerId: carbet.ownerId,
|
||||
|
|
|
|||
50
src/lib/pirogue-providers.ts
Normal file
50
src/lib/pirogue-providers.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* Helpers Plugin pirogue-providers.
|
||||
*/
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export type PirogueProvider = {
|
||||
id: string;
|
||||
name: string;
|
||||
contactEmail: string | null;
|
||||
contactPhone: string | null;
|
||||
rivers: string[];
|
||||
pricingNote: string | null;
|
||||
description: string | null;
|
||||
active: boolean;
|
||||
};
|
||||
|
||||
export async function listActiveProviders(): Promise<PirogueProvider[]> {
|
||||
const rows = await prisma.pirogueProvider.findMany({
|
||||
where: { active: true },
|
||||
orderBy: { name: "asc" },
|
||||
});
|
||||
return rows.map((r) => ({
|
||||
id: r.id,
|
||||
name: r.name,
|
||||
contactEmail: r.contactEmail,
|
||||
contactPhone: r.contactPhone,
|
||||
rivers: r.rivers,
|
||||
pricingNote: r.pricingNote,
|
||||
description: r.description,
|
||||
active: r.active,
|
||||
}));
|
||||
}
|
||||
|
||||
export async function listProvidersForRiver(river: string): Promise<PirogueProvider[]> {
|
||||
const all = await listActiveProviders();
|
||||
return all.filter((p) => p.rivers.some((r) => r.toLowerCase() === river.toLowerCase()));
|
||||
}
|
||||
|
||||
export const TRANSPORT_MODE_LABEL: Record<string, string> = {
|
||||
OWNER_PROVIDES: "Le loueur fournit le passeur",
|
||||
SELF_ARRANGE: "À organiser par le voyageur",
|
||||
PARTNER_PROVIDER: "Partenaire référencé",
|
||||
};
|
||||
|
||||
export const TRANSPORT_MODE_EMOJI: Record<string, string> = {
|
||||
OWNER_PROVIDES: "👤",
|
||||
SELF_ARRANGE: "🗺️",
|
||||
PARTNER_PROVIDER: "🤝",
|
||||
};
|
||||
|
|
@ -25,6 +25,10 @@ import {
|
|||
seedLegalPages,
|
||||
unpublishLegalPages,
|
||||
} from "./seeds/legal-pages-default";
|
||||
import {
|
||||
deactivatePirogueProviders,
|
||||
seedPirogueProviders,
|
||||
} from "./seeds/pirogue-providers-default";
|
||||
|
||||
export const pluginHooks: Record<string, PluginHookSet | undefined> = {
|
||||
"demo-carbets-seed": {
|
||||
|
|
@ -67,4 +71,16 @@ export const pluginHooks: Record<string, PluginHookSet | undefined> = {
|
|||
console.log(`[plugin legal-pages] disable: ${unpub} pages dépubliées`);
|
||||
},
|
||||
},
|
||||
"pirogue-providers": {
|
||||
onEnable: async () => {
|
||||
const { providers, carbets } = await seedPirogueProviders();
|
||||
console.log(
|
||||
`[plugin pirogue-providers] seed: ${providers} partenaires, ${carbets} carbets attachés`,
|
||||
);
|
||||
},
|
||||
onDisable: async () => {
|
||||
const count = await deactivatePirogueProviders();
|
||||
console.log(`[plugin pirogue-providers] disable: ${count} partenaires désactivés`);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
104
src/lib/plugins/seeds/pirogue-providers-default.ts
Normal file
104
src/lib/plugins/seeds/pirogue-providers-default.ts
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
* Seed du plugin `pirogue-providers` : 3 prestataires partenaires fictifs
|
||||
* réalistes pour la démo, attachés à 4 fleuves majeurs de Guyane.
|
||||
*/
|
||||
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
const PROVIDERS = [
|
||||
{
|
||||
id: "demo-provider-maroni",
|
||||
name: "Pirogues du Maroni",
|
||||
contactEmail: "contact@pirogues-maroni.demo",
|
||||
contactPhone: "+594-694-100200",
|
||||
rivers: ["Maroni", "Lawa"],
|
||||
pricingNote: "≈ 150 € aller-retour depuis Apatou (selon distance carbet)",
|
||||
description:
|
||||
"Coopérative de piroguiers bushinengués. Aller-retour vers les carbets en aval d'Apatou, départs matin. Capacité 6-8 passagers, vestes de pluie fournies.",
|
||||
},
|
||||
{
|
||||
id: "demo-provider-approuague",
|
||||
name: "Approuague Aventures",
|
||||
contactEmail: "info@approuague-aventures.demo",
|
||||
contactPhone: "+594-694-300400",
|
||||
rivers: ["Approuague"],
|
||||
pricingNote: "≈ 250 € aller-retour Régina, ≈ 320 € jusqu'au saut Mapaou",
|
||||
description:
|
||||
"Prestataire historique de l'Approuague, basé à Régina. Pirogues 4 passagers + matériel. Possibilité de jour blanc (pêche, observation) en option.",
|
||||
},
|
||||
{
|
||||
id: "demo-provider-oyapock",
|
||||
name: "Oyapock Frontière",
|
||||
contactEmail: "contact@oyapock-frontiere.demo",
|
||||
contactPhone: "+594-694-500600",
|
||||
rivers: ["Oyapock"],
|
||||
pricingNote: "≈ 300 € aller-retour Saint-Georges (haute eau), tarif majoré en étiage",
|
||||
description:
|
||||
"Trajet vers les carbets côté Guyane et côté Brésilien (Vila Brasil). En étiage (oct-nov), prévoir une marge horaire — fond du fleuve parfois imprévisible.",
|
||||
},
|
||||
] as const;
|
||||
|
||||
const CARBET_PROVIDER_LINKS = [
|
||||
{ slug: "demo-karbe-awara-maroni", providerId: "demo-provider-maroni", mode: "PARTNER_PROVIDER" as const },
|
||||
{ slug: "demo-karbe-maripa-approuague", providerId: "demo-provider-approuague", mode: "PARTNER_PROVIDER" as const },
|
||||
{ slug: "demo-karbe-paripou-oyapock", providerId: "demo-provider-oyapock", mode: "PARTNER_PROVIDER" as const },
|
||||
{ slug: "demo-karbe-wapa-comte", providerId: null, mode: "OWNER_PROVIDES" as const },
|
||||
{ slug: "demo-karbe-mahury-ce-hopital", providerId: null, mode: "OWNER_PROVIDES" as const },
|
||||
{ slug: "demo-karbe-kourou-couleuvre", providerId: null, mode: "SELF_ARRANGE" as const },
|
||||
];
|
||||
|
||||
export async function seedPirogueProviders(): Promise<{ providers: number; carbets: number }> {
|
||||
let providers = 0;
|
||||
for (const p of PROVIDERS) {
|
||||
await prisma.pirogueProvider.upsert({
|
||||
where: { id: p.id },
|
||||
update: {
|
||||
name: p.name,
|
||||
contactEmail: p.contactEmail,
|
||||
contactPhone: p.contactPhone,
|
||||
rivers: [...p.rivers],
|
||||
pricingNote: p.pricingNote,
|
||||
description: p.description,
|
||||
active: true,
|
||||
},
|
||||
create: {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
contactEmail: p.contactEmail,
|
||||
contactPhone: p.contactPhone,
|
||||
rivers: [...p.rivers],
|
||||
pricingNote: p.pricingNote,
|
||||
description: p.description,
|
||||
active: true,
|
||||
},
|
||||
});
|
||||
providers += 1;
|
||||
}
|
||||
|
||||
let carbets = 0;
|
||||
for (const link of CARBET_PROVIDER_LINKS) {
|
||||
const updated = await prisma.carbet.updateMany({
|
||||
where: { slug: link.slug },
|
||||
data: {
|
||||
pirogueProviderId: link.providerId,
|
||||
transportMode: link.mode,
|
||||
},
|
||||
});
|
||||
carbets += updated.count;
|
||||
}
|
||||
|
||||
return { providers, carbets };
|
||||
}
|
||||
|
||||
export async function deactivatePirogueProviders(): Promise<number> {
|
||||
const result = await prisma.pirogueProvider.updateMany({
|
||||
where: { id: { startsWith: "demo-provider-" } },
|
||||
data: { active: false },
|
||||
});
|
||||
// Détache aussi les carbets démo
|
||||
await prisma.carbet.updateMany({
|
||||
where: { pirogueProviderId: { startsWith: "demo-provider-" } },
|
||||
data: { pirogueProviderId: null, transportMode: null },
|
||||
});
|
||||
return result.count;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue