mirror of
https://github.com/R0m1k3/PleinR.git
synced 2026-10-23 23:28:04 +02:00
Approuver une demande cree directement l'adherent + compte
- approveMembershipRequest : cree la fiche adherent (statut actif) et son compte de connexion (mot de passe temporaire), marque la demande approuvee - Bouton "Approuver & creer" redirige vers la fiche (login + mdp visibles) - Demande sans e-mail : erreur explicite (creation manuelle requise) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
e2dc695d3e
commit
e31c71caa9
2 files changed
+59
-4
No files matched your search
@@ -429,6 +429,54 @@ export async function updateOwnProfile(formData: FormData) {
|
|||||||
revalidatePath("/");
|
revalidatePath("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Approuve une demande d'adhésion ET crée directement l'adhérent + son compte
|
||||||
|
// de connexion (mot de passe temporaire). Renvoie l'id du nouvel adhérent.
|
||||||
|
export async function approveMembershipRequest(formData: FormData): Promise<number | undefined> {
|
||||||
|
const { role } = await requireRole();
|
||||||
|
if (!can(role, "manageMembers")) throw new Error("Accès refusé");
|
||||||
|
|
||||||
|
const id = Number(formData.get("id"));
|
||||||
|
if (!id) return undefined;
|
||||||
|
|
||||||
|
const [req] = await db.select().from(membershipRequests).where(eq(membershipRequests.id, id));
|
||||||
|
if (!req) throw new Error("Demande introuvable.");
|
||||||
|
|
||||||
|
const email = (req.email ?? "").trim().toLowerCase();
|
||||||
|
if (!email) {
|
||||||
|
throw new Error("Cette demande n'a pas d'e-mail : impossible de créer le compte. Créez l'adhérent manuellement.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const existing = await db.select({ id: users.id }).from(users).where(eq(users.email, email));
|
||||||
|
if (existing.length > 0) {
|
||||||
|
throw new Error("Un compte existe déjà avec cet e-mail.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const [newMember] = await db
|
||||||
|
.insert(members)
|
||||||
|
.values({ name: req.name, email, status: "active" })
|
||||||
|
.returning({ id: members.id });
|
||||||
|
|
||||||
|
const tempPassword = generateTempPassword();
|
||||||
|
await db.insert(users).values({
|
||||||
|
name: req.name,
|
||||||
|
email,
|
||||||
|
role: "member",
|
||||||
|
memberId: newMember.id,
|
||||||
|
passwordHash: await bcrypt.hash(tempPassword, 10),
|
||||||
|
tempPassword,
|
||||||
|
mustChangePassword: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.update(membershipRequests).set({ status: "approved" }).where(eq(membershipRequests.id, id));
|
||||||
|
await logActivity(`Demande approuvée : adhérent <strong>${req.name}</strong> créé`, "#1f8a5b");
|
||||||
|
|
||||||
|
revalidatePath("/backend/demandes");
|
||||||
|
revalidatePath("/backend/adherents");
|
||||||
|
revalidatePath("/backend");
|
||||||
|
revalidatePath("/");
|
||||||
|
return newMember.id;
|
||||||
|
}
|
||||||
|
|
||||||
// ---- Inbox: membership requests + contact messages ----
|
// ---- Inbox: membership requests + contact messages ----
|
||||||
export async function setRequestStatus(formData: FormData) {
|
export async function setRequestStatus(formData: FormData) {
|
||||||
const { role } = await requireRole();
|
const { role } = await requireRole();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { auth } from "@/auth";
|
|||||||
import { db } from "@/db";
|
import { db } from "@/db";
|
||||||
import { contactMessages, membershipRequests } from "@/db/schema";
|
import { contactMessages, membershipRequests } from "@/db/schema";
|
||||||
import { can } from "@/lib/rbac";
|
import { can } from "@/lib/rbac";
|
||||||
import { setContactStatus, setRequestStatus } from "../actions";
|
import { approveMembershipRequest, setContactStatus, setRequestStatus } from "../actions";
|
||||||
|
|
||||||
export const dynamic = "force-dynamic";
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
@@ -51,6 +51,14 @@ export default async function DemandesPage() {
|
|||||||
db.select().from(contactMessages).orderBy(desc(contactMessages.createdAt)),
|
db.select().from(contactMessages).orderBy(desc(contactMessages.createdAt)),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Approuver = créer l'adhérent + son compte, puis aller sur sa fiche
|
||||||
|
// (login + mot de passe temporaire y sont affichés).
|
||||||
|
async function handleApprove(fd: FormData) {
|
||||||
|
"use server";
|
||||||
|
const id = await approveMembershipRequest(fd);
|
||||||
|
redirect(id ? `/backend/adherents/${id}` : "/backend/demandes");
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ display: "flex", flexDirection: "column", gap: 26 }}>
|
<div style={{ display: "flex", flexDirection: "column", gap: 26 }}>
|
||||||
{/* ---- Demandes d'adhésion ---- */}
|
{/* ---- Demandes d'adhésion ---- */}
|
||||||
@@ -72,10 +80,9 @@ export default async function DemandesPage() {
|
|||||||
</div>
|
</div>
|
||||||
<StatusPill map={REQ_STATUS} status={r.status} />
|
<StatusPill map={REQ_STATUS} status={r.status} />
|
||||||
<div style={{ display: "flex", gap: 8 }}>
|
<div style={{ display: "flex", gap: 8 }}>
|
||||||
<form action={setRequestStatus}>
|
<form action={handleApprove}>
|
||||||
<input type="hidden" name="id" value={r.id} />
|
<input type="hidden" name="id" value={r.id} />
|
||||||
<input type="hidden" name="status" value="approved" />
|
<ActionBtn color="#1f8a5b">Approuver & créer</ActionBtn>
|
||||||
<ActionBtn color="#1f8a5b">Approuver</ActionBtn>
|
|
||||||
</form>
|
</form>
|
||||||
<form action={setRequestStatus}>
|
<form action={setRequestStatus}>
|
||||||
<input type="hidden" name="id" value={r.id} />
|
<input type="hidden" name="id" value={r.id} />
|
||||||
|
|||||||
Reference in new issue
Block a user