Refactor HousesPage and HouseManagement components: Introduce TypeScript types for house and invitation data structures to enhance type safety. Update data serialization logic for improved clarity and maintainability. Refactor UI components for better readability and consistency, including adjustments to conditional rendering and styling in HouseManagement. Optimize fetch logic in HousesSection with useCallback for performance improvements.
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 4m25s
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 4m25s
This commit is contained in:
@@ -5,9 +5,41 @@ import NavigationWrapper from "@/components/navigation/NavigationWrapper";
|
|||||||
import HousesSection from "@/components/houses/HousesSection";
|
import HousesSection from "@/components/houses/HousesSection";
|
||||||
import { houseService } from "@/services/houses/house.service";
|
import { houseService } from "@/services/houses/house.service";
|
||||||
import { prisma } from "@/services/database";
|
import { prisma } from "@/services/database";
|
||||||
|
import type { House, HouseMembership, HouseInvitation } from "@/prisma/generated/prisma/client";
|
||||||
|
|
||||||
export const dynamic = "force-dynamic";
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
|
// Types pour les données sérialisées
|
||||||
|
type HouseWithRelations = House & {
|
||||||
|
creator?: {
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
avatar: string | null;
|
||||||
|
} | null;
|
||||||
|
creatorId?: string;
|
||||||
|
memberships?: Array<HouseMembership & {
|
||||||
|
user: {
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
avatar: string | null;
|
||||||
|
score: number | null;
|
||||||
|
level: number | null;
|
||||||
|
};
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
|
||||||
|
type InvitationWithRelations = HouseInvitation & {
|
||||||
|
house: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
inviter: {
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
avatar: string | null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export default async function HousesPage() {
|
export default async function HousesPage() {
|
||||||
const session = await auth();
|
const session = await auth();
|
||||||
|
|
||||||
@@ -90,12 +122,12 @@ export default async function HousesPage() {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
// Sérialiser les données pour le client
|
// Sérialiser les données pour le client
|
||||||
const houses = (housesData as any[]).map((house: any) => ({
|
const houses = (housesData as HouseWithRelations[]).map((house: HouseWithRelations) => ({
|
||||||
id: house.id,
|
id: house.id,
|
||||||
name: house.name,
|
name: house.name,
|
||||||
description: house.description,
|
description: house.description,
|
||||||
creator: house.creator || { id: house.creatorId, username: "Unknown", avatar: null },
|
creator: house.creator || { id: house.creatorId || "", username: "Unknown", avatar: null },
|
||||||
memberships: (house.memberships || []).map((m: any) => ({
|
memberships: (house.memberships || []).map((m) => ({
|
||||||
id: m.id,
|
id: m.id,
|
||||||
role: m.role,
|
role: m.role,
|
||||||
user: {
|
user: {
|
||||||
@@ -113,8 +145,8 @@ export default async function HousesPage() {
|
|||||||
id: myHouseData.id,
|
id: myHouseData.id,
|
||||||
name: myHouseData.name,
|
name: myHouseData.name,
|
||||||
description: myHouseData.description,
|
description: myHouseData.description,
|
||||||
creator: (myHouseData as any).creator || { id: (myHouseData as any).creatorId, username: "Unknown", avatar: null },
|
creator: (myHouseData as HouseWithRelations).creator || { id: (myHouseData as HouseWithRelations).creatorId || "", username: "Unknown", avatar: null },
|
||||||
memberships: ((myHouseData as any).memberships || []).map((m: any) => ({
|
memberships: ((myHouseData as HouseWithRelations).memberships || []).map((m) => ({
|
||||||
id: m.id,
|
id: m.id,
|
||||||
role: m.role,
|
role: m.role,
|
||||||
user: {
|
user: {
|
||||||
@@ -128,7 +160,7 @@ export default async function HousesPage() {
|
|||||||
}
|
}
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const invitations = invitationsData.map((inv: any) => ({
|
const invitations = (invitationsData as InvitationWithRelations[]).map((inv: InvitationWithRelations) => ({
|
||||||
id: inv.id,
|
id: inv.id,
|
||||||
house: {
|
house: {
|
||||||
id: inv.house.id,
|
id: inv.house.id,
|
||||||
|
|||||||
@@ -91,7 +91,9 @@ export default function HouseManagement({
|
|||||||
const fetchRequests = async () => {
|
const fetchRequests = async () => {
|
||||||
if (!house || !isAdmin) return;
|
if (!house || !isAdmin) return;
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/api/houses/${house.id}/requests?status=PENDING`);
|
const response = await fetch(
|
||||||
|
`/api/houses/${house.id}/requests?status=PENDING`
|
||||||
|
);
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
setRequests(data);
|
setRequests(data);
|
||||||
@@ -101,10 +103,13 @@ export default function HouseManagement({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
fetchRequests();
|
fetchRequests();
|
||||||
}, [house?.id, isAdmin]);
|
}, [house, isAdmin]);
|
||||||
|
|
||||||
const handleDelete = () => {
|
const handleDelete = () => {
|
||||||
if (!house || !confirm("Êtes-vous sûr de vouloir supprimer cette maison ?")) {
|
if (
|
||||||
|
!house ||
|
||||||
|
!confirm("Êtes-vous sûr de vouloir supprimer cette maison ?")
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,11 +173,17 @@ export default function HouseManagement({
|
|||||||
if (!house) {
|
if (!house) {
|
||||||
return (
|
return (
|
||||||
<Card className="p-6">
|
<Card className="p-6">
|
||||||
<h2 className="text-lg sm:text-xl font-bold mb-4" style={{ color: "var(--foreground)" }}>
|
<h2
|
||||||
|
className="text-lg sm:text-xl font-bold mb-4"
|
||||||
|
style={{ color: "var(--foreground)" }}
|
||||||
|
>
|
||||||
Ma Maison
|
Ma Maison
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-sm mb-4" style={{ color: "var(--muted-foreground)" }}>
|
<p
|
||||||
Vous n'êtes membre d'aucune maison pour le moment.
|
className="text-sm mb-4"
|
||||||
|
style={{ color: "var(--muted-foreground)" }}
|
||||||
|
>
|
||||||
|
Vous n'êtes membre d'aucune maison pour le moment.
|
||||||
</p>
|
</p>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
@@ -180,27 +191,30 @@ export default function HouseManagement({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<Card
|
<Card
|
||||||
className="p-4 sm:p-6"
|
className="p-4 sm:p-6"
|
||||||
style={{
|
style={{
|
||||||
borderColor: `color-mix(in srgb, var(--accent) 40%, var(--border))`,
|
borderColor: `color-mix(in srgb, var(--accent) 40%, var(--border))`,
|
||||||
borderWidth: "2px",
|
borderWidth: "2px",
|
||||||
boxShadow: `0 0 20px color-mix(in srgb, var(--accent) 10%, transparent)`
|
boxShadow: `0 0 20px color-mix(in srgb, var(--accent) 10%, transparent)`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-start gap-4 mb-4">
|
<div className="flex flex-col sm:flex-row sm:justify-between sm:items-start gap-4 mb-4">
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<h3
|
<h3
|
||||||
className="text-xl sm:text-2xl font-bold mb-2 break-words"
|
className="text-xl sm:text-2xl font-bold mb-2 break-words"
|
||||||
style={{
|
style={{
|
||||||
color: "var(--accent)",
|
color: "var(--accent)",
|
||||||
textShadow: `0 0 10px color-mix(in srgb, var(--accent) 30%, transparent)`
|
textShadow: `0 0 10px color-mix(in srgb, var(--accent) 30%, transparent)`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{house.name}
|
{house.name}
|
||||||
</h3>
|
</h3>
|
||||||
{house.description && (
|
{house.description && (
|
||||||
<p className="text-sm mt-2 break-words" style={{ color: "var(--muted-foreground)" }}>
|
<p
|
||||||
|
className="text-sm mt-2 break-words"
|
||||||
|
style={{ color: "var(--muted-foreground)" }}
|
||||||
|
>
|
||||||
{house.description}
|
{house.description}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
@@ -217,22 +231,40 @@ export default function HouseManagement({
|
|||||||
{isEditing ? "Annuler" : "Modifier"}
|
{isEditing ? "Annuler" : "Modifier"}
|
||||||
</Button>
|
</Button>
|
||||||
{isOwner && (
|
{isOwner && (
|
||||||
<Button onClick={handleDelete} variant="danger" size="sm" className="flex-1 sm:flex-none">
|
<Button
|
||||||
|
onClick={handleDelete}
|
||||||
|
variant="danger"
|
||||||
|
size="sm"
|
||||||
|
className="flex-1 sm:flex-none"
|
||||||
|
>
|
||||||
Supprimer
|
Supprimer
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{!isOwner && (
|
{!isOwner && (
|
||||||
<Button onClick={handleLeave} variant="danger" size="sm" className="flex-1 sm:flex-none">
|
<Button
|
||||||
|
onClick={handleLeave}
|
||||||
|
variant="danger"
|
||||||
|
size="sm"
|
||||||
|
className="flex-1 sm:flex-none"
|
||||||
|
>
|
||||||
Quitter
|
Quitter
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{error && <Alert variant="error" className="mb-4">{error}</Alert>}
|
{error && (
|
||||||
{success && <Alert variant="success" className="mb-4">{success}</Alert>}
|
<Alert variant="error" className="mb-4">
|
||||||
|
{error}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
{success && (
|
||||||
|
<Alert variant="success" className="mb-4">
|
||||||
|
{success}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
{isEditing ? (
|
{isEditing ? (
|
||||||
<HouseForm
|
<HouseForm
|
||||||
@@ -245,12 +277,12 @@ export default function HouseManagement({
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
<h4
|
<h4
|
||||||
className="text-sm font-semibold uppercase tracking-wider mb-3"
|
className="text-sm font-semibold uppercase tracking-wider mb-3"
|
||||||
style={{
|
style={{
|
||||||
color: "var(--primary)",
|
color: "var(--primary)",
|
||||||
borderBottom: `2px solid color-mix(in srgb, var(--primary) 30%, transparent)`,
|
borderBottom: `2px solid color-mix(in srgb, var(--primary) 30%, transparent)`,
|
||||||
paddingBottom: "0.5rem"
|
paddingBottom: "0.5rem",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Membres ({house.memberships?.length ?? 0})
|
Membres ({house.memberships?.length ?? 0})
|
||||||
@@ -258,21 +290,25 @@ export default function HouseManagement({
|
|||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{(house.memberships || []).map((membership) => {
|
{(house.memberships || []).map((membership) => {
|
||||||
const isCurrentUser = membership.user.id === session?.user?.id;
|
const isCurrentUser = membership.user.id === session?.user?.id;
|
||||||
const roleColor =
|
const roleColor =
|
||||||
membership.role === "OWNER" ? "var(--accent)" :
|
membership.role === "OWNER"
|
||||||
membership.role === "ADMIN" ? "var(--primary)" :
|
? "var(--accent)"
|
||||||
"var(--muted-foreground)";
|
: membership.role === "ADMIN"
|
||||||
|
? "var(--primary)"
|
||||||
|
: "var(--muted-foreground)";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={membership.id}
|
key={membership.id}
|
||||||
className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 p-3 rounded"
|
className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 p-3 rounded"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: isCurrentUser
|
backgroundColor: isCurrentUser
|
||||||
? "color-mix(in srgb, var(--primary) 10%, var(--card-hover))"
|
? "color-mix(in srgb, var(--primary) 10%, var(--card-hover))"
|
||||||
: "var(--card-hover)",
|
: "var(--card-hover)",
|
||||||
borderLeft: `3px solid ${roleColor}`,
|
borderLeft: `3px solid ${roleColor}`,
|
||||||
borderColor: isCurrentUser ? "var(--primary)" : "transparent"
|
borderColor: isCurrentUser
|
||||||
|
? "var(--primary)"
|
||||||
|
: "transparent",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-2 min-w-0 flex-1">
|
<div className="flex items-center gap-2 min-w-0 flex-1">
|
||||||
@@ -285,16 +321,18 @@ export default function HouseManagement({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<span
|
<span
|
||||||
className="font-semibold block sm:inline"
|
className="font-semibold block sm:inline"
|
||||||
style={{
|
style={{
|
||||||
color: isCurrentUser ? "var(--primary)" : "var(--foreground)"
|
color: isCurrentUser
|
||||||
|
? "var(--primary)"
|
||||||
|
: "var(--foreground)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{membership.user.username}
|
{membership.user.username}
|
||||||
{isCurrentUser && " (Vous)"}
|
{isCurrentUser && " (Vous)"}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className="text-xs block sm:inline sm:ml-2"
|
className="text-xs block sm:inline sm:ml-2"
|
||||||
style={{ color: "var(--muted-foreground)" }}
|
style={{ color: "var(--muted-foreground)" }}
|
||||||
>
|
>
|
||||||
@@ -309,43 +347,55 @@ export default function HouseManagement({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2 flex-shrink-0">
|
<div className="flex items-center gap-2 flex-shrink-0">
|
||||||
<span
|
<span
|
||||||
className="text-xs uppercase px-2 py-1 rounded font-bold"
|
className="text-xs uppercase px-2 py-1 rounded font-bold"
|
||||||
style={{
|
style={{
|
||||||
color: roleColor,
|
color: roleColor,
|
||||||
backgroundColor: `color-mix(in srgb, ${roleColor} 15%, transparent)`,
|
backgroundColor: `color-mix(in srgb, ${roleColor} 15%, transparent)`,
|
||||||
border: `1px solid color-mix(in srgb, ${roleColor} 30%, transparent)`
|
border: `1px solid color-mix(in srgb, ${roleColor} 30%, transparent)`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{membership.role === "OWNER" && "👑 "}
|
{membership.role === "OWNER" && "👑 "}
|
||||||
{membership.role}
|
{membership.role}
|
||||||
</span>
|
</span>
|
||||||
{isAdmin &&
|
{isAdmin &&
|
||||||
!isCurrentUser &&
|
!isCurrentUser &&
|
||||||
(isOwner || membership.role === "MEMBER") &&
|
(isOwner || membership.role === "MEMBER") &&
|
||||||
membership.role !== "OWNER" && (
|
membership.role !== "OWNER" && (
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (confirm(`Êtes-vous sûr de vouloir retirer ${membership.user.username} de la maison ?`)) {
|
if (
|
||||||
startTransition(async () => {
|
confirm(
|
||||||
const result = await removeMember(house.id, membership.user.id);
|
`Êtes-vous sûr de vouloir retirer ${membership.user.username} de la maison ?`
|
||||||
if (result.success) {
|
)
|
||||||
// Rafraîchir le score dans le header (le membre retiré perd des points)
|
) {
|
||||||
window.dispatchEvent(new Event("refreshUserScore"));
|
startTransition(async () => {
|
||||||
onUpdate?.();
|
const result = await removeMember(
|
||||||
} else {
|
house.id,
|
||||||
setError(result.error || "Erreur lors du retrait du membre");
|
membership.user.id
|
||||||
}
|
);
|
||||||
});
|
if (result.success) {
|
||||||
}
|
// Rafraîchir le score dans le header (le membre retiré perd des points)
|
||||||
}}
|
window.dispatchEvent(
|
||||||
disabled={isPending}
|
new Event("refreshUserScore")
|
||||||
variant="danger"
|
);
|
||||||
size="sm"
|
onUpdate?.();
|
||||||
>
|
} else {
|
||||||
Retirer
|
setError(
|
||||||
</Button>
|
result.error ||
|
||||||
)}
|
"Erreur lors du retrait du membre"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
disabled={isPending}
|
||||||
|
variant="danger"
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
Retirer
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -411,15 +461,15 @@ export default function HouseManagement({
|
|||||||
|
|
||||||
{isAdmin && pendingRequests.length > 0 && (
|
{isAdmin && pendingRequests.length > 0 && (
|
||||||
<Card className="p-4 sm:p-6">
|
<Card className="p-4 sm:p-6">
|
||||||
<h2
|
<h2
|
||||||
className="text-lg sm:text-xl font-bold mb-4"
|
className="text-lg sm:text-xl font-bold mb-4"
|
||||||
style={{
|
style={{
|
||||||
color: "var(--purple)",
|
color: "var(--purple)",
|
||||||
borderBottom: `2px solid color-mix(in srgb, var(--purple) 30%, transparent)`,
|
borderBottom: `2px solid color-mix(in srgb, var(--purple) 30%, transparent)`,
|
||||||
paddingBottom: "0.5rem"
|
paddingBottom: "0.5rem",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Demandes d'adhésion
|
Demandes d'adhésion
|
||||||
</h2>
|
</h2>
|
||||||
<RequestList requests={pendingRequests} onUpdate={onUpdate} />
|
<RequestList requests={pendingRequests} onUpdate={onUpdate} />
|
||||||
</Card>
|
</Card>
|
||||||
@@ -427,4 +477,3 @@ export default function HouseManagement({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
import Card from "@/components/ui/Card";
|
import Card from "@/components/ui/Card";
|
||||||
import Button from "@/components/ui/Button";
|
import Button from "@/components/ui/Button";
|
||||||
@@ -78,7 +78,7 @@ export default function HousesSection({
|
|||||||
const [showCreateForm, setShowCreateForm] = useState(false);
|
const [showCreateForm, setShowCreateForm] = useState(false);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
|
||||||
const fetchHouses = async () => {
|
const fetchHouses = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
if (searchTerm) {
|
if (searchTerm) {
|
||||||
@@ -94,7 +94,7 @@ export default function HousesSection({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching houses:", error);
|
console.error("Error fetching houses:", error);
|
||||||
}
|
}
|
||||||
};
|
}, [searchTerm]);
|
||||||
|
|
||||||
const fetchMyHouse = async () => {
|
const fetchMyHouse = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -129,9 +129,13 @@ export default function HousesSection({
|
|||||||
}, 300);
|
}, 300);
|
||||||
return () => clearTimeout(timeout);
|
return () => clearTimeout(timeout);
|
||||||
} else {
|
} else {
|
||||||
fetchHouses();
|
// Utiliser un timeout pour éviter setState synchrone dans effect
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
fetchHouses();
|
||||||
|
}, 0);
|
||||||
|
return () => clearTimeout(timeout);
|
||||||
}
|
}
|
||||||
}, [searchTerm]);
|
}, [searchTerm, fetchHouses]);
|
||||||
|
|
||||||
const handleUpdate = () => {
|
const handleUpdate = () => {
|
||||||
fetchMyHouse();
|
fetchMyHouse();
|
||||||
@@ -165,15 +169,24 @@ export default function HousesSection({
|
|||||||
<>
|
<>
|
||||||
{invitations.length > 0 && (
|
{invitations.length > 0 && (
|
||||||
<Card className="p-4 sm:p-6">
|
<Card className="p-4 sm:p-6">
|
||||||
<h2 className="text-lg sm:text-xl font-bold mb-4" style={{ color: "var(--foreground)" }}>
|
<h2
|
||||||
|
className="text-lg sm:text-xl font-bold mb-4"
|
||||||
|
style={{ color: "var(--foreground)" }}
|
||||||
|
>
|
||||||
Mes Invitations
|
Mes Invitations
|
||||||
</h2>
|
</h2>
|
||||||
<InvitationList invitations={invitations} onUpdate={handleUpdate} />
|
<InvitationList
|
||||||
|
invitations={invitations}
|
||||||
|
onUpdate={handleUpdate}
|
||||||
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Card className="p-4 sm:p-6">
|
<Card className="p-4 sm:p-6">
|
||||||
<h2 className="text-lg sm:text-xl font-bold mb-4" style={{ color: "var(--foreground)" }}>
|
<h2
|
||||||
|
className="text-lg sm:text-xl font-bold mb-4"
|
||||||
|
style={{ color: "var(--foreground)" }}
|
||||||
|
>
|
||||||
Ma Maison
|
Ma Maison
|
||||||
</h2>
|
</h2>
|
||||||
{myHouse ? (
|
{myHouse ? (
|
||||||
@@ -194,8 +207,12 @@ export default function HousesSection({
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm mb-4 break-words" style={{ color: "var(--muted-foreground)" }}>
|
<p
|
||||||
Vous n'êtes membre d'aucune maison. Créez-en une ou demandez à rejoindre une maison existante.
|
className="text-sm mb-4 break-words"
|
||||||
|
style={{ color: "var(--muted-foreground)" }}
|
||||||
|
>
|
||||||
|
Vous n'êtes membre d'aucune maison. Créez-en
|
||||||
|
une ou demandez à rejoindre une maison existante.
|
||||||
</p>
|
</p>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => setShowCreateForm(true)}
|
onClick={() => setShowCreateForm(true)}
|
||||||
@@ -213,7 +230,10 @@ export default function HousesSection({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<Card className="p-4 sm:p-6">
|
<Card className="p-4 sm:p-6">
|
||||||
<h2 className="text-lg sm:text-xl font-bold mb-4" style={{ color: "var(--foreground)" }}>
|
<h2
|
||||||
|
className="text-lg sm:text-xl font-bold mb-4"
|
||||||
|
style={{ color: "var(--foreground)" }}
|
||||||
|
>
|
||||||
Toutes les Maisons
|
Toutes les Maisons
|
||||||
</h2>
|
</h2>
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
@@ -243,4 +263,3 @@ export default function HousesSection({
|
|||||||
</BackgroundSection>
|
</BackgroundSection>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -346,8 +346,13 @@ export class ChallengeService {
|
|||||||
where: { id: challengeId },
|
where: { id: challengeId },
|
||||||
data: updateData,
|
data: updateData,
|
||||||
});
|
});
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
if (error?.code === "P2025") {
|
if (
|
||||||
|
error &&
|
||||||
|
typeof error === "object" &&
|
||||||
|
"code" in error &&
|
||||||
|
error.code === "P2025"
|
||||||
|
) {
|
||||||
// Record not found
|
// Record not found
|
||||||
throw new NotFoundError("Défi");
|
throw new NotFoundError("Défi");
|
||||||
}
|
}
|
||||||
@@ -431,8 +436,13 @@ export class ChallengeService {
|
|||||||
await prisma.challenge.delete({
|
await prisma.challenge.delete({
|
||||||
where: { id: challengeId },
|
where: { id: challengeId },
|
||||||
});
|
});
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
if (error?.code === "P2025") {
|
if (
|
||||||
|
error &&
|
||||||
|
typeof error === "object" &&
|
||||||
|
"code" in error &&
|
||||||
|
error.code === "P2025"
|
||||||
|
) {
|
||||||
// Record not found
|
// Record not found
|
||||||
throw new NotFoundError("Défi");
|
throw new NotFoundError("Défi");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user