Skip to content

Commit

Permalink
fix: event detail and rating component (#60)
Browse files Browse the repository at this point in the history
fix :
- event detail
- Rating component

Co-authored-by: alexandre-kakal-akarah <[email protected]>
  • Loading branch information
alexandre-kakal and alexandre-kakal-akarah authored Aug 28, 2024
1 parent 4a99336 commit b89d606
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 221 deletions.
243 changes: 48 additions & 195 deletions src/app/(app)/evenements/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,123 +1,26 @@
"use client";

import React, { useEffect, useState } from "react";
import React, { Suspense } from "react";
import ParallaxImage from "@/components/clients/ParallaxImage";
import Rating from "@/components/Rating";
import { Icons } from "@/components/Icons";
import TopBar from "@/components/TopBar";
import dynamic from "next/dynamic";
import { UserEvent, Event } from "@prisma/client";
import { JourneyWithStepsAndComments } from "@/types/journey";
import Rating from "@/components/Rating";
import { format } from "date-fns";
import { signIn, useSession } from "next-auth/react";
import { Button } from "@/components/ui/button";
import { useRouter } from "next/navigation";

const LeafletEventMap = dynamic(() => import("@/components/map/EventMap"), {
ssr: false,
});

type Params = { id: number };

const EventDetail = ({ params }: { params: Params }) => {
const router = useRouter();
const [event, setEvent] = useState<Event | null>(null);
const [journey, setJourney] = useState<JourneyWithStepsAndComments | null>(
null,
);
const [isJoined, setIsJoined] = useState(false);
const [participantCount, setParticipantCount] = useState(0);
const { data: session } = useSession();

useEffect(() => {
const fetchEventData = async () => {
try {
const eventResponse = await fetch(
`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/events/${params.id}`,
);
const eventData = await eventResponse.json();
setEvent(eventData.data);
setParticipantCount(eventData.data.userEvents.length);

const journeyResponse = await fetch(
`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/journeys/${eventData.data.journeyId}`,
);
const journeyData = await journeyResponse.json();
setJourney(journeyData.data);

if (session) {
const userJoined = eventData.data.userEvents.some(
(userEvent: UserEvent) => userEvent.userId === session.user.id,
);
setIsJoined(userJoined);
}
} catch (error) {
console.error("Error fetching event or journey data:", error);
}
};
import { getEventByIdWithUserEvents } from "@/services/eventService";
import { getJourneyById } from "@/services/journeyService";
import { notFound } from "next/navigation";
import ParticipantActions from "@/components/clients/ParticipantActions";
import EventMap from "@/components/clients/EventMap";

fetchEventData();
}, [params.id, session]);
type Params = { id: string };

const handleJoin = async () => {
if (!session) {
signIn();
return;
}
const EventDetail = async ({ params }: { params: Params }) => {
const event = await getEventByIdWithUserEvents(Number(params.id));
if (!event) return notFound();

try {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/events/${event!.id}/join/${session!.user.id}`,
{
method: "POST",
headers: {
authorization: `Bearer ${session!.accessToken}`,
},
},
);
if (response.ok) {
setIsJoined(true);
setParticipantCount(participantCount + 1);
} else {
console.error("Failed to join the event");
}
} catch (error) {
console.error("Error joining the event:", error);
}
};
const journey = await getJourneyById(event.journeyId);
if (!journey) return notFound();

const handleLeave = async () => {
try {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/events/${event!.id}/leave/${session!.user.id}`,
{
method: "DELETE",
headers: {
authorization: `Bearer ${session!.accessToken}`,
},
},
);
if (response.ok) {
setIsJoined(false);
setParticipantCount(participantCount - 1);
} else {
console.error("Failed to leave the event");
}
} catch (error) {
console.error("Error leaving the event:", error);
}
};

const handleStart = async () => {
router.push(`${params.id}/start`);
};

if (!event || !journey) {
return <div>Loading...</div>;
}

const firstStep = journey?.steps?.[0];
const isEventStartable = isJoined && new Date() >= new Date(event.startAt);
const participantCount = event.userEvents.length;
const firstStep = journey.steps[0];

return (
<main className="flex min-h-screen flex-col bg-background">
Expand All @@ -126,61 +29,12 @@ const EventDetail = ({ params }: { params: Params }) => {
<ParallaxImage src={event.image} alt={event.title} />
<div className="-translate-y-4 bg-slate-100 px-5 pb-5 pt-7 shadow-lg">
<div className="flex justify-between">
<div>
{isEventStartable && (
<div>
<Button
className="mt-1 border-blue-700 bg-blue-600 p-2 text-white shadow-xl hover:bg-blue-500"
onClick={handleStart}
>
<span>Lancer l'événement</span>
<Icons.arrowLink
stroke="#f0f0f0"
width={20}
height={20}
className="ml-2"
/>{" "}
</Button>
</div>
)}
</div>
<div>
{isJoined ? (
// <button
// onClick={handleLeave}
// className="rounded bg-red-500 min-w-10 px-4 py-2 text-white"
// >
// Quitter
// </button>
<Button
className="mt-1 border-red-600 bg-red-600 p-2 text-white shadow-xl hover:bg-red-500"
onClick={handleLeave}
>
<span>Quitter l'évènement</span>
<Icons.close width={14} height={14} className="ml-2" />
</Button>
) : (
// <button
// onClick={handleJoin}
// className="rounded bg-orange px-4 py-2 text-white"
// >
// Rejoindre
// </button>
<Button
onClick={handleJoin}
type="submit"
className="mt-1 border-orange bg-orange p-2 text-white shadow-xl hover:bg-orange"
>
<span>Rejoindre</span>
<Icons.arrowLink
stroke="#f0f0f0"
width={20}
height={20}
className="ml-2"
/>
</Button>
)}
</div>
<Suspense fallback={<div>Loading actions...</div>}>
<ParticipantActions
event={event}
participantCount={participantCount}
/>
</Suspense>
</div>
<h1 className="mb-5 mt-4 text-4xl font-extrabold text-orange">
{event.title}
Expand All @@ -189,7 +43,7 @@ const EventDetail = ({ params }: { params: Params }) => {
<div className="flex items-center gap-1 text-orange">
<Icons.mapPin />
<p className="text-sm font-medium text-orange">
{journey.steps[0]?.city || "Unknown"}
{firstStep?.city || "Unknown"}
</p>
</div>
</div>
Expand Down Expand Up @@ -232,7 +86,7 @@ const EventDetail = ({ params }: { params: Params }) => {
{firstStep && (
<>
<h2 className="mt-8 text-lg font-semibold text-orange">Map</h2>
<LeafletEventMap
<EventMap
longitude={firstStep.longitude}
latitude={firstStep.latitude}
name={firstStep.puzzle}
Expand Down Expand Up @@ -269,32 +123,31 @@ const EventDetail = ({ params }: { params: Params }) => {
<h2 className="text-lg font-semibold text-orange">Parcours</h2>
<div className="flex flex-col items-start gap-2 rounded-lg pl-4">
<div className="flex w-full items-center gap-4 rounded-lg border border-gray-600 bg-slate-200 p-4 shadow-md">
<div className="flex w-full items-center gap-4 rounded-lg border border-gray-600 bg-slate-200 p-4 shadow-md">
<ParallaxImage
src={
journey.steps[0]?.picturePuzzle ||
"https://picsum.photos/200"
}
alt={journey.steps[0]?.puzzle}
/>
<div>
<h3 className=" text-lg font-semibold">{journey.title}</h3>
<p className=" text-sm">
{journey.steps[0]?.city || "Unknown"}
</p>
<div className="flex items-center">
<Rating
rating={
journey.comments.length > 0
? journey.comments.reduce(
(sum, comment) => sum + (comment.rating ?? 0),
0,
) / journey.comments.length
: 0
}
ratingCount={journey.comments.length}
/>
</div>
<ParallaxImage
src={
journey.steps[0]?.picturePuzzle ||
"https://picsum.photos/200"
}
alt={journey.steps[0]?.puzzle}
/>
<div>
<h3 className=" text-lg font-semibold">{journey.title}</h3>
<p className=" text-sm">
{journey.steps[0]?.city || "Unknown"}
</p>
<div className="flex items-center">
<Rating
rating={
journey.comments.length > 0
? journey.comments.reduce(
(sum, comment) => sum + (comment.rating ?? 0),
0,
) / journey.comments.length
: 0
}
ratingCount={journey.comments.length}
hasCommentCount
/>
</div>
</div>
</div>
Expand Down
22 changes: 1 addition & 21 deletions src/app/(app)/parcours/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,6 @@ const levelIntToText = (level: number) => {
}
};

// const LevelBullet = ({ level }: { level: string }) => {
// switch (level) {
// case "unaccessible":
// return (
// <div className="absolute right-[6px] top-[6px] size-[10px] rounded-full bg-level-1" />
// );
// case "partiallyAccessible":
// return (
// <div className="absolute right-[6px] top-[6px] size-[10px] rounded-full bg-level-2" />
// );
// case "accessible":
// return (
// <div className="absolute right-[6px] top-[6px] size-[10px] rounded-full bg-level-3" />
// );
// default:
// return (
// <div className="absolute right-[6px] top-[6px] size-[10px] rounded-full bg-level" />
// );
// }
// };

const JourneyUI = async (id: string) => {
const journey = await getSingleJourney(id);
if (!journey) return notFound();
Expand Down Expand Up @@ -151,6 +130,7 @@ const JourneyUI = async (id: string) => {
<Rating
rating={averageRating}
ratingCount={journey.comments.length}
hasCommentCount
/>
{journey.comments.map((comment) => (
<div key={comment.id} className="mb-3 flex flex-col gap-1">
Expand Down
10 changes: 7 additions & 3 deletions src/components/JourneyCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@ const JourneyCard = ({ journey }: JourneyCardProps) => {
<h2 className="mb-2 font-semibold">{journey.title}</h2>
<div className="mb-2 flex">
<div className="flex flex-wrap gap-[6px]">
<div className="flex flex-shrink-0 items-center rounded-md bg-slate-300 px-2 py-[6px]">
<div className="flex shrink-0 items-center rounded-md bg-slate-300 px-2 py-[6px]">
<Icons.dumbbel />
<p className="text-sm font-semibold text-gray">
{phisicalDificulty}
</p>
</div>
<div className="flex flex-shrink-0 items-center gap-1 rounded-md bg-slate-300 px-2 py-[6px]">
<div className="flex shrink-0 items-center gap-1 rounded-md bg-slate-300 px-2 py-[6px]">
<Icons.bulb />
<p className="text-sm font-semibold text-gray">
{cluesDificulty}
Expand All @@ -78,7 +78,11 @@ const JourneyCard = ({ journey }: JourneyCardProps) => {
</div>
</div>
<p className="mb-4 text-sm">{journey.description}</p>
<Rating rating={averageRate} ratingCount={journey.comments.length} />
<Rating
rating={averageRate}
ratingCount={journey.comments.length}
hasCommentCount
/>
<div className="mt-auto flex items-center justify-between">
<div className="flex items-center gap-1 text-orange">
<Icons.mapPin />
Expand Down
11 changes: 9 additions & 2 deletions src/components/Rating.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ import { Icons } from "./Icons";
type RatingProps = {
rating: number;
ratingCount: number;
hasCommentCount?: boolean;
};

const Rating = ({ rating, ratingCount }: RatingProps) => {
const Rating = ({
rating,
ratingCount,
hasCommentCount = false,
}: RatingProps) => {
const fullStars = Math.floor(rating);
const halfStars = rating % 1 !== 0 ? 1 : 0;
const emptyStars = 5 - fullStars - halfStars;
Expand All @@ -28,7 +33,9 @@ const Rating = ({ rating, ratingCount }: RatingProps) => {
return (
<div className="mb-3 mt-1 flex items-start">
{stars}
<p className="ml-1 text-[16px] text-orange-700">{`(${ratingCount} avis)`}</p>
{hasCommentCount && (
<p className="ml-1 text-[16px] text-orange-700">{`(${ratingCount} avis)`}</p>
)}
</div>
);
};
Expand Down
20 changes: 20 additions & 0 deletions src/components/clients/EventMap.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"use client";

import dynamic from "next/dynamic";
import React from "react";

const LeafletEventMap = dynamic(() => import("@/components/map/EventMap"), {
ssr: false,
});

const EventMap = ({
longitude,
latitude,
name,
}: {
longitude: any;
latitude: any;
name: any;
}) => <LeafletEventMap longitude={longitude} latitude={latitude} name={name} />;

export default EventMap;
Loading

0 comments on commit b89d606

Please sign in to comment.