Refactor ChallengesSection component to utilize initial challenges and users data: Replace fetching logic with props for challenges and users, streamline challenge creation with a dedicated form component, and enhance UI for better user experience.
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 2m49s
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 2m49s
This commit is contained in:
@@ -3,6 +3,8 @@ import { auth } from "@/lib/auth";
|
||||
import { getBackgroundImage } from "@/lib/preferences";
|
||||
import NavigationWrapper from "@/components/navigation/NavigationWrapper";
|
||||
import ChallengesSection from "@/components/challenges/ChallengesSection";
|
||||
import { challengeService } from "@/services/challenges/challenge.service";
|
||||
import { userService } from "@/services/users/user.service";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
@@ -13,15 +15,41 @@ export default async function ChallengesPage() {
|
||||
redirect("/login");
|
||||
}
|
||||
|
||||
const backgroundImage = await getBackgroundImage(
|
||||
"challenges",
|
||||
"/got-2.jpg"
|
||||
);
|
||||
const [challengesRaw, users, backgroundImage] = await Promise.all([
|
||||
challengeService.getUserChallenges(session.user.id),
|
||||
userService
|
||||
.getAllUsers({
|
||||
orderBy: {
|
||||
username: "asc",
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
avatar: true,
|
||||
score: true,
|
||||
level: true,
|
||||
},
|
||||
})
|
||||
.then((users) => users.filter((user) => user.id !== session.user.id)),
|
||||
getBackgroundImage("challenges", "/got-2.jpg"),
|
||||
]);
|
||||
|
||||
// Convertir les dates Date en string pour correspondre au type attendu par le composant
|
||||
const challenges = challengesRaw.map((challenge) => ({
|
||||
...challenge,
|
||||
createdAt: challenge.createdAt.toISOString(),
|
||||
acceptedAt: challenge.acceptedAt?.toISOString() ?? null,
|
||||
completedAt: challenge.completedAt?.toISOString() ?? null,
|
||||
}));
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-black relative">
|
||||
<NavigationWrapper />
|
||||
<ChallengesSection backgroundImage={backgroundImage} />
|
||||
<ChallengesSection
|
||||
initialChallenges={challenges}
|
||||
initialUsers={users}
|
||||
backgroundImage={backgroundImage}
|
||||
/>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
Button,
|
||||
Input,
|
||||
Textarea,
|
||||
Select,
|
||||
Card,
|
||||
Badge,
|
||||
Alert,
|
||||
@@ -22,6 +23,7 @@ export default function StyleGuidePage() {
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
const [inputValue, setInputValue] = useState("");
|
||||
const [textareaValue, setTextareaValue] = useState("");
|
||||
const [selectValue, setSelectValue] = useState("");
|
||||
const [rating, setRating] = useState(0);
|
||||
|
||||
return (
|
||||
@@ -170,6 +172,74 @@ export default function StyleGuidePage() {
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Select */}
|
||||
<Card variant="dark" className="p-6 mb-8">
|
||||
<h2 className="text-2xl font-bold text-pixel-gold mb-6">Select</h2>
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Basique</h3>
|
||||
<div className="max-w-md">
|
||||
<Select
|
||||
label="Sélectionner une option"
|
||||
value={selectValue}
|
||||
onChange={(e) => setSelectValue(e.target.value)}
|
||||
>
|
||||
<option value="">Choisir...</option>
|
||||
<option value="option1">Option 1</option>
|
||||
<option value="option2">Option 2</option>
|
||||
<option value="option3">Option 3</option>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Sans label</h3>
|
||||
<div className="max-w-md">
|
||||
<Select
|
||||
value={selectValue}
|
||||
onChange={(e) => setSelectValue(e.target.value)}
|
||||
>
|
||||
<option value="">Choisir...</option>
|
||||
<option value="option1">Option 1</option>
|
||||
<option value="option2">Option 2</option>
|
||||
<option value="option3">Option 3</option>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Avec erreur</h3>
|
||||
<div className="max-w-md">
|
||||
<Select
|
||||
label="Select avec erreur"
|
||||
value={selectValue}
|
||||
onChange={(e) => setSelectValue(e.target.value)}
|
||||
error="Veuillez sélectionner une option"
|
||||
>
|
||||
<option value="">Choisir...</option>
|
||||
<option value="option1">Option 1</option>
|
||||
<option value="option2">Option 2</option>
|
||||
<option value="option3">Option 3</option>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Disabled</h3>
|
||||
<div className="max-w-md">
|
||||
<Select
|
||||
label="Select désactivé"
|
||||
value={selectValue}
|
||||
onChange={(e) => setSelectValue(e.target.value)}
|
||||
disabled
|
||||
>
|
||||
<option value="">Choisir...</option>
|
||||
<option value="option1">Option 1</option>
|
||||
<option value="option2">Option 2</option>
|
||||
<option value="option3">Option 3</option>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Badges */}
|
||||
<Card variant="dark" className="p-6 mb-8">
|
||||
<h2 className="text-2xl font-bold text-pixel-gold mb-6">Badges</h2>
|
||||
@@ -187,6 +257,9 @@ export default function StyleGuidePage() {
|
||||
<div>
|
||||
<h3 className="text-lg text-gray-300 mb-3">Tailles</h3>
|
||||
<div className="flex flex-wrap items-center gap-4">
|
||||
<Badge variant="default" size="xs">
|
||||
Extra Small
|
||||
</Badge>
|
||||
<Badge variant="default" size="sm">
|
||||
Small
|
||||
</Badge>
|
||||
|
||||
Reference in New Issue
Block a user