From b1fbcaa86aea7a37a614972d5323a5561ae8e6fd Mon Sep 17 00:00:00 2001 From: Elad Abutbul Date: Thu, 11 Dec 2025 11:06:12 +0200 Subject: [PATCH 1/3] elad-abutbul --- src/App.tsx | 13 +++++++- src/components/showCard/ShowCard.tsx | 49 ++++++++++++++++++---------- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index b16f189..091187a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -56,7 +56,18 @@ export default function App() {
- {/* TODO - shows.map((show)=>{ return })*/} + {shows.map((show) => { + return ( + + ); + })}
diff --git a/src/components/showCard/ShowCard.tsx b/src/components/showCard/ShowCard.tsx index 7e18a47..80cbb27 100644 --- a/src/components/showCard/ShowCard.tsx +++ b/src/components/showCard/ShowCard.tsx @@ -9,16 +9,33 @@ export interface ShowCardProps { image: string; } -export default function ShowCard( - /* TODO 1: Accept props with ShowCardProps type here */ -) { +export default function ShowCard({ + artist, + stage, + day, + hour, + ticketsLeft, + image, +}: ShowCardProps) { // TODO 2: Create state called isInterested of type boolean (default false) - // const [isInterested, setIsInterested] = ... - + const [isInterested, setISInterested] = useState(false); // TODO 3: Function that toggles true/false in isInterested - // function handleToggleInterested() {} + function handleToggleInterested() { + setISInterested(prev => !prev); + } // TODO 4: Create ticketsStatusText (string): + const ticketsStatusText = + ticketsLeft === 0 + ? "SOLD OUT" + : ticketsLeft <= 30 + ? "Last tickets โ€“ hurry up!" + : "Tickets available"; + + const interestedText = isInterested + ? "This show is in your interested list ๐ŸŽŸ๏ธ" + : "You haven't added this show yet"; + // 0 โ†’ "SOLD OUT" // 1โ€“30 โ†’ "Last tickets โ€“ hurry up!" // >30 โ†’ "Tickets available" @@ -31,42 +48,38 @@ export default function ShowCard(
{/* TODO 6: Replace placeholder with real from props */} - {/* {artist} */} -
Image goes here
+ {artist}

{/* TODO 7: If isInterested โ†’ show โญ before artist name */} - "Artist name here" + {isInterested ? "โญ " : ""} + {artist}

- {/* TODO 8: Display stage, day, hour from props */} - "Stage ยท Day ยท Hour" + {stage} ยท {day} ยท {hour}

{/* TODO 9: Display the ticketsStatusText */} - "Tickets status text" + {ticketsStatusText}

{/* TODO 10: Display the interestedText */} - "Interested status text" + {interestedText}

); From 2a5e6136fc91a87543232dda37c161f63a789778 Mon Sep 17 00:00:00 2001 From: Elad Abutbul Date: Sat, 13 Dec 2025 15:33:47 +0200 Subject: [PATCH 2/3] fixed pl --- src/App.tsx | 11 +---- src/components/showCard/ShowCard.tsx | 63 ++++++---------------------- src/constants/showCardConstants.ts | 12 ++++++ src/hooks/useInterested.ts | 14 +++++++ src/interfaces/show.ts | 8 ++++ src/utils/showCardUtils.ts | 21 ++++++++++ 6 files changed, 69 insertions(+), 60 deletions(-) create mode 100644 src/constants/showCardConstants.ts create mode 100644 src/hooks/useInterested.ts create mode 100644 src/interfaces/show.ts create mode 100644 src/utils/showCardUtils.ts diff --git a/src/App.tsx b/src/App.tsx index 091187a..91df51a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -57,16 +57,7 @@ export default function App() {
{shows.map((show) => { - return ( - - ); + return ; })}
diff --git a/src/components/showCard/ShowCard.tsx b/src/components/showCard/ShowCard.tsx index 80cbb27..df4900f 100644 --- a/src/components/showCard/ShowCard.tsx +++ b/src/components/showCard/ShowCard.tsx @@ -1,13 +1,9 @@ -import { useState } from "react"; - -export interface ShowCardProps { - artist: string; - stage: string; - day: string; - hour: string; - ticketsLeft: number; - image: string; -} +import { useInterested } from "../../hooks/useInterested"; +import { + getInterestedStatusText, + getTicketsStatusText, +} from "../../utils/showCardUtils"; +import type { Show } from "../../interfaces/show"; export default function ShowCard({ artist, @@ -16,44 +12,21 @@ export default function ShowCard({ hour, ticketsLeft, image, -}: ShowCardProps) { - // TODO 2: Create state called isInterested of type boolean (default false) - const [isInterested, setISInterested] = useState(false); - // TODO 3: Function that toggles true/false in isInterested - function handleToggleInterested() { - setISInterested(prev => !prev); - } - - // TODO 4: Create ticketsStatusText (string): - const ticketsStatusText = - ticketsLeft === 0 - ? "SOLD OUT" - : ticketsLeft <= 30 - ? "Last tickets โ€“ hurry up!" - : "Tickets available"; +}: Show) { - const interestedText = isInterested - ? "This show is in your interested list ๐ŸŽŸ๏ธ" - : "You haven't added this show yet"; + const { isInterested, toggleInterested } = useInterested(); - // 0 โ†’ "SOLD OUT" - // 1โ€“30 โ†’ "Last tickets โ€“ hurry up!" - // >30 โ†’ "Tickets available" - - // TODO 5: Create text for interest status based on isInterested: - // false โ†’ "You haven't added this show yet" - // true โ†’ "This show is in your interested list ๐ŸŽŸ๏ธ" + const ticketsStatusText = getTicketsStatusText(ticketsLeft); + const interestedText = getInterestedStatusText(isInterested); return (
- {/* TODO 6: Replace placeholder with real from props */} {artist}

- {/* TODO 7: If isInterested โ†’ show โญ before artist name */} {isInterested ? "โญ " : ""} {artist}

@@ -63,22 +36,12 @@ export default function ShowCard({
-

- {/* TODO 9: Display the ticketsStatusText */} - {ticketsStatusText} -

+

{ticketsStatusText}

-

- {/* TODO 10: Display the interestedText */} - {interestedText} -

+

{interestedText}

-
diff --git a/src/constants/showCardConstants.ts b/src/constants/showCardConstants.ts new file mode 100644 index 0000000..1765d6d --- /dev/null +++ b/src/constants/showCardConstants.ts @@ -0,0 +1,12 @@ +export const SHOW_CARD_CONSTANTS = { + SOLD_OUT: "SOLD OUT", + LAST_TICKETS: "Last tickets โ€“ hurry up!", + TICKETS_AVAILABLE: "Tickets available", + YOUR_INTERESTED_LIST: "This show is in your interested list ๐ŸŽŸ๏ธ", + NO_ADDED_SHOW: "You haven't added this show yet", +} as const; + +export const SHOW_CARD_LIMITS = { + SOLD_OUT: 0, + LAST_TICKETS_THRESHOLD: 30, +} as const; diff --git a/src/hooks/useInterested.ts b/src/hooks/useInterested.ts new file mode 100644 index 0000000..6e02765 --- /dev/null +++ b/src/hooks/useInterested.ts @@ -0,0 +1,14 @@ +import { useState } from "react"; + +export function useInterested() { + const [isInterested, setIsInterested] = useState(false); + + function toggleInterested() { + setIsInterested((prev) => !prev); + } + + return { + isInterested, + toggleInterested, + }; +} diff --git a/src/interfaces/show.ts b/src/interfaces/show.ts new file mode 100644 index 0000000..2aa51df --- /dev/null +++ b/src/interfaces/show.ts @@ -0,0 +1,8 @@ +export interface Show { + artist: string; + stage: string; + day: string; + hour: string; + ticketsLeft: number; + image: string; +} \ No newline at end of file diff --git a/src/utils/showCardUtils.ts b/src/utils/showCardUtils.ts new file mode 100644 index 0000000..36918b6 --- /dev/null +++ b/src/utils/showCardUtils.ts @@ -0,0 +1,21 @@ +import { + SHOW_CARD_CONSTANTS, + SHOW_CARD_LIMITS, +} from "../constants/showCardConstants"; + +export function getTicketsStatusText(ticketsLeft: number): string { + if (ticketsLeft === SHOW_CARD_LIMITS.SOLD_OUT) { + return SHOW_CARD_CONSTANTS.SOLD_OUT; + } + if (ticketsLeft <= SHOW_CARD_LIMITS.LAST_TICKETS_THRESHOLD) { + return SHOW_CARD_CONSTANTS.LAST_TICKETS; + } + return SHOW_CARD_CONSTANTS.TICKETS_AVAILABLE; +} + +export function getInterestedStatusText(isInterested: boolean): string { + if (isInterested) { + return SHOW_CARD_CONSTANTS.YOUR_INTERESTED_LIST; + } + return SHOW_CARD_CONSTANTS.NO_ADDED_SHOW; +} From 90c40d82704b64d30da9501a8419e89c6f851513 Mon Sep 17 00:00:00 2001 From: Elad Abutbul Date: Sat, 13 Dec 2025 15:46:39 +0200 Subject: [PATCH 3/3] project structure for good practices --- src/components/showCard/ShowCard.tsx | 14 +++++++------- src/constants/showCardConstants.ts | 9 +++++++++ src/utils/showCardUtils.ts | 12 ++++++++++++ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/components/showCard/ShowCard.tsx b/src/components/showCard/ShowCard.tsx index df4900f..4ce44d5 100644 --- a/src/components/showCard/ShowCard.tsx +++ b/src/components/showCard/ShowCard.tsx @@ -1,9 +1,7 @@ -import { useInterested } from "../../hooks/useInterested"; -import { - getInterestedStatusText, - getTicketsStatusText, -} from "../../utils/showCardUtils"; +import { getArtistPrefix, getInterestedButtonText } from "../../utils/showCardUtils"; +import {getInterestedStatusText,getTicketsStatusText} from "../../utils/showCardUtils"; import type { Show } from "../../interfaces/show"; +import { useInterested } from "../../hooks/useInterested"; export default function ShowCard({ artist, @@ -18,6 +16,8 @@ export default function ShowCard({ const ticketsStatusText = getTicketsStatusText(ticketsLeft); const interestedText = getInterestedStatusText(isInterested); + const artistPrefix = getArtistPrefix(isInterested); + const buttonText = getInterestedButtonText(isInterested); return (
@@ -27,7 +27,7 @@ export default function ShowCard({

- {isInterested ? "โญ " : ""} + {artistPrefix} {artist}

@@ -42,7 +42,7 @@ export default function ShowCard({

); diff --git a/src/constants/showCardConstants.ts b/src/constants/showCardConstants.ts index 1765d6d..f52aedd 100644 --- a/src/constants/showCardConstants.ts +++ b/src/constants/showCardConstants.ts @@ -10,3 +10,12 @@ export const SHOW_CARD_LIMITS = { SOLD_OUT: 0, LAST_TICKETS_THRESHOLD: 30, } as const; + +export const SHOW_CARD_BUTTON_TEXT = { + REMOVE: "Remove from my list", + ADD: "Mark as interested", +} as const; + +export const SHOW_CARD_UI = { + INTERESTED_ICON: "โญ ", +} as const; diff --git a/src/utils/showCardUtils.ts b/src/utils/showCardUtils.ts index 36918b6..488fe77 100644 --- a/src/utils/showCardUtils.ts +++ b/src/utils/showCardUtils.ts @@ -1,6 +1,8 @@ import { + SHOW_CARD_BUTTON_TEXT, SHOW_CARD_CONSTANTS, SHOW_CARD_LIMITS, + SHOW_CARD_UI, } from "../constants/showCardConstants"; export function getTicketsStatusText(ticketsLeft: number): string { @@ -19,3 +21,13 @@ export function getInterestedStatusText(isInterested: boolean): string { } return SHOW_CARD_CONSTANTS.NO_ADDED_SHOW; } + +export function getArtistPrefix(isInterested: boolean): string { + return isInterested ? SHOW_CARD_UI.INTERESTED_ICON : ""; +} + +export function getInterestedButtonText(isInterested: boolean): string { + return isInterested + ? SHOW_CARD_BUTTON_TEXT.REMOVE + : SHOW_CARD_BUTTON_TEXT.ADD; +}