Skip to content

Commit

Permalink
Merge pull request #119 from bleu/juliano/op-664-implement-hifi-for-t…
Browse files Browse the repository at this point in the history
…racks-list-page

Implement hifi for tracks list page
  • Loading branch information
juliano-quatrin-nunes authored Jan 10, 2025
2 parents ca009c8 + 60e35d8 commit 7f2454a
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 94 deletions.
Binary file added apps/govquests-frontend/public/badges/track1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions apps/govquests-frontend/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@
--primary: 0 0% 100%; /* White */
--primary-foreground: 0 0% 0% /* Black text */;

--secondary: 228 9% 23%; /* Dark grey #333640 */
--secondary-foreground: 0 0% 100%;
--secondary: 0 0% 82%; /* Dark grey 210 210 210 */
--secondary-foreground: 0 0% 0%;

--muted: 228 9% 23%;
--muted-foreground: 0 0% 64%;
Expand Down
7 changes: 6 additions & 1 deletion apps/govquests-frontend/src/components/IndicatorPill.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ export const IndicatorPill = ({
...props
}: ComponentProps<"span">) => {
return (
<div className="relative border shadow-[1px_1px_0px_0px_#000000] bg-primary border-primary-foreground items-center text-center rounded-lg justify-center flex py-1 px-4">
<div
className={cn(
"relative border shadow-[1px_1px_0px_0px_#000000] bg-primary border-primary-foreground items-center text-center rounded-lg justify-center flex py-1 px-4",
className,
)}
>
<AnchorPoint className="absolute top-1 left-1 " />
<span
className="text-primary-foreground text-xs font-bold whitespace-nowrap flex items-center"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,82 +1,45 @@
import Link from "next/link";
import type React from "react";

import Image from "@/components/ui/Image";
import { Quests } from "../types/questTypes";
import { IndicatorPill } from "@/components/IndicatorPill";
import { cn } from "@/lib/utils";
import RewardIndicator from "@/components/RewardIndicator";
import { Quests } from "../types/questTypes";

interface QuestProps {
quest: Quests[number];
}

const QuestCard: React.FC<QuestProps> = ({ quest }) => {
const status = quest.userQuests?.[0]?.status || "unstarted";
const disabled = status === "completed";

const peelClassName =
"bg-primary/50 text-white backdrop-blur-sm border border-primary/20";
const isCompleted = status === "completed";

return (
<Link
href={`/quests/${quest.slug}`}
className={cn(
"group flex flex-col bg-primary/10 border border-primary/20 rounded-lg overflow-hidden transition-all duration-200",
disabled ? "cursor-default" : "hover:shadow-md hover:bg-primary/15",
)}
>
<div className="relative w-full h-48 overflow-hidden">
<div className="absolute w-21 left-0 right-0 top-0 z-10 p-3 flex flex-col gap-3 justify-between items-start">
{disabled ? (
<span
className={cn(
"bg-secondary font-normal py-1 px-2 rounded-md text-sm ml-1 flex gap-1 p-auto w-21",
peelClassName,
)}
>
Completed
</span>
) : (
quest.rewardPools
.toReversed()
.map(({ rewardDefinition: reward }) => (
<RewardIndicator
key={reward.type}
reward={reward}
className={peelClassName}
/>
))
)}
</div>
{quest.displayData.imageUrl ? (
<Image
src={quest.displayData.imageUrl}
alt={`QuestCard ${quest.displayData.title} image`}
className={cn(
"object-cover w-full h-full transition-transform duration-200",
!disabled && "group-hover:scale-105",
)}
/>
) : (
<div className="w-full h-full bg-primary/5" />
)}
</div>
<div className={cn("flex flex-col p-7 gap-4", disabled && "opacity-60")}>
<h3
<Link href={`/quests/${quest.slug}`}>
<div className="rounded-lg overflow-hidden group transition-all duration-300 hover:shadow-lg">
<div
className={cn(
"font-semibold text-lg leading-tight line-clamp-2 transition-colors flex gap-2",
!disabled && "group-hover:text-primary/90",
"relative bg-secondary flex justify-center items-center p-6",
isCompleted && "bg-gradient-to-b from-[#80F2FF] to-[#A1E0D2]",
)}
>
{quest.displayData.title}
</h3>
<p className="text-sm text-foreground/70 line-clamp-3">
<span
dangerouslySetInnerHTML={{
__html: quest.displayData.intro || "",
}}
/>
</p>
<div className="w-full text-center text-primary-foreground font-bold text-lg py-3 bg-primary border border-primary-foreground shadow-[1px_1px_0px_0px_#000000] rounded-lg transition-all duration-300 group-hover:shadow-[2px_2px_0px_0px_#000000] group-hover:scale-105">
{quest.displayData.title}
</div>
<IndicatorPill className="absolute bottom-0 left-1/2 -translate-x-1/2 translate-y-1/2">
{isCompleted
? "Completed"
: quest.rewardPools[0].rewardDefinition.amount + " points"}
</IndicatorPill>
</div>
<div className="bg-background/60 h-full p-7">
<p className="text-sm text-foreground line-clamp-4">
<span
dangerouslySetInnerHTML={{
__html: quest.displayData.intro || "",
}}
/>
</p>
</div>
</div>
</Link>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ interface BadgeCardProps {
}

export const BadgeCard = ({ badge, isCompleted }: BadgeCardProps) => {
// TODO - Add badge image - OP-671
return (
<div className="relative items-center justify-center min-w-52 h-60 col-span-2">
<Link href={`/badges/${badge.id}`}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,21 @@ import { TrackAccordionHeader } from "./TrackAccordionHeader";
import { TrackDescription } from "./TrackDescription";

export const TrackAccordion = ({ track }: { track: Tracks[number] }) => {
const isCompleted = track.quests
.map((quest) => quest.userQuests[0]?.status)
.every((status) => status === "completed");
return (
<Accordion
type="single"
collapsible
className="border rounded-lg bg-background/60"
className="border border-primary-foreground/10 rounded-lg bg-background/60"
>
<AccordionItem value="item-1">
<AccordionTrigger className="px-10 py-5 text-foreground">
<TrackAccordionHeader track={track} />
<TrackAccordionHeader track={track} isCompleted={isCompleted} />
</AccordionTrigger>
<AccordionContent>
<TrackDescription track={track} />
<TrackDescription track={track} isCompleted={isCompleted} />
<QuestCarousel quests={track.quests} />
</AccordionContent>
</AccordionItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,23 @@ import { Tracks } from "../../types/trackTypes";

interface TrackAccordionHeader {
track: Tracks[number];
isCompleted: boolean;
}

export const TrackAccordionHeader = ({ track }: TrackAccordionHeader) => {
export const TrackAccordionHeader = ({
track,
isCompleted,
}: TrackAccordionHeader) => {
return (
<div className="flex justify-between items-center w-full pr-10">
<h1 className="text-2xl font-bold flex gap-2">
<p className="text-foreground/60">#TRACK</p> {track.displayData.title}
</h1>
<div className="flex gap-4 hover:no-underline">
<IndicatorPill>{track.quests.length} quests</IndicatorPill>
<IndicatorPill>{track.points} points</IndicatorPill>
<IndicatorPill>
{isCompleted ? "Completed" : track.points + " points"}
</IndicatorPill>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { BadgeCard } from "./BadgeCard";
import { Tracks } from "../../types/trackTypes";

export const TrackDescription = ({ track }: { track: Tracks[number] }) => {
interface TrackDescriptionProps {
track: Tracks[number];
isCompleted: boolean;
}

export const TrackDescription = ({
track,
isCompleted,
}: TrackDescriptionProps) => {
const badge = { id: "1", image: "/badge/track1.png", title: "Track Badge" };

return (
Expand All @@ -14,8 +22,15 @@ export const TrackDescription = ({ track }: { track: Tracks[number] }) => {
<div className="border-b h-0 w-full" />
</div>
<div className="items-center justify-center flex gap-12 mx-20">
<BadgeCard badge={badge} isCompleted={false} />
<div className="col-span-8 w-full">{track.displayData.description}</div>
<BadgeCard badge={badge} isCompleted={isCompleted} />
<div className="flex flex-col gap-4 col-span-8 w-full font-bold">
<span>{track.displayData.description}</span>
<span>
{isCompleted
? `Track completed — ${badge.title} unlocked. `
: "Complete all quests to Unlock this Track Badge."}
</span>
</div>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ export const TrackList = () => {
data && (
<div className="max-w-[1200px] mx-auto">
<div className="flex flex-col border-b mb-7 pb-2 gap-2">
<h1 className="text-2xl font-bold text-black/80"># Tracks</h1>
<h2 className="text-xl font-normal text-black/80">
<h1 className="text-2xl font-bold"># Tracks</h1>
<h2 className="text-xl font-normal">
Complete quests to earn points and unlock rewards.
</h2>
</div>
Expand Down
46 changes: 28 additions & 18 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 7f2454a

Please sign in to comment.