Skip to content

Commit

Permalink
feat: add reminderCard to landing page
Browse files Browse the repository at this point in the history
  • Loading branch information
BrunoAseff authored Jan 28, 2025
1 parent 00a34c9 commit da72e88
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import { Pause } from "@/components/icons/pause";
import { Play } from "@/components/icons/Play";

import IconBtn from "@/components/nova/buttons/IconBtn";
import Waves from "../icons/ambientSound/Waves";
import Rain from "../icons/ambientSound/Rain";
import Birds from "../icons/ambientSound/Birds";
import Fire from "../icons/ambientSound/Fire";
import Underwater from "../icons/ambientSound/Underwater";
import Cafe from "../icons/ambientSound/Cafe";
import Beach from "../icons/ambientSound/Beach";
import Tropical from "../icons/ambientSound/Tropical";
import HeavyRain from "../icons/ambientSound/HeavyRain";
import Waves from "../../icons/ambientSound/Waves";
import Rain from "../../icons/ambientSound/Rain";
import Birds from "../../icons/ambientSound/Birds";
import Fire from "../../icons/ambientSound/Fire";
import Underwater from "../../icons/ambientSound/Underwater";
import Cafe from "../../icons/ambientSound/Cafe";
import Beach from "../../icons/ambientSound/Beach";
import Tropical from "../../icons/ambientSound/Tropical";
import HeavyRain from "../../icons/ambientSound/HeavyRain";

export const AmbientSoundCard = () => {
const {
Expand Down
76 changes: 76 additions & 0 deletions src/components/landing-page/Cards/QuoteCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { Refresh } from "@/components/icons/Refresh";
import IconBtn from "@/components/nova/buttons/IconBtn";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { quotes, type Quote } from "@/components/features/quotes/quotes";

export const QuoteCard = () => {
const [currentQuote, setCurrentQuote] = useState<Quote>(
quotes[Math.floor(Math.random() * quotes.length)] ?? {
text: "",
author: "",
category: "Motivational",
},
);

const refreshQuote = () => {
const newQuote = quotes[Math.floor(Math.random() * quotes.length)] ?? {
text: "",
author: "",
category: "Motivational",
};
setCurrentQuote(newQuote);
};

return (
<div className="group w-full max-w-md rounded-2xl border-[1px] border-accent/20 bg-accent-foreground p-4 font-montserrat">
<div className="relative">
<AnimatePresence mode="wait">
<motion.div
key={currentQuote.text}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.3 }}
className="flex flex-col gap-2 text-left"
>
<p className="text-sm font-medium text-gray-100 md:text-xl">
&ldquo;{currentQuote.text}&rdquo;
</p>
<p className="text-xs text-gray-100 md:text-sm">
- {currentQuote.author}
</p>
</motion.div>
</AnimatePresence>

<TooltipProvider>
<Tooltip delayDuration={0}>
<TooltipTrigger asChild>
<IconBtn
onClick={refreshQuote}
variant="default"
className="absolute bottom-2 right-2 border-[1px] border-transparent bg-transparent text-foreground opacity-0 transition-opacity hover:border-white/60 hover:bg-white/5 group-hover:opacity-100"
>
<Refresh />
</IconBtn>
</TooltipTrigger>
<TooltipContent
id="refresh"
className="font-inter flex items-center gap-3 text-xs font-medium"
>
Refresh quote
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
</div>
);
};

export default QuoteCard;
127 changes: 127 additions & 0 deletions src/components/landing-page/Cards/RemindersCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import React, { useState } from "react";
import { Textarea } from "@/components/ui/textarea";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import {
PuzzlePiece,
FlowerLotus,
Clover,
HandHeart,
ShootingStar,
Brain,
} from "@phosphor-icons/react";

type ReminderType = keyof typeof typeStyles;

const typeStyles = {
Gratitude: {
icon: FlowerLotus,
color: "#F5A524",
},
Motivation: {
icon: Clover,
color: "#10b981",
},
Affirmation: {
icon: HandHeart,
color: "#ec4899",
},
Challenge: {
icon: PuzzlePiece,
color: "#F31260",
},
Dream: {
icon: ShootingStar,
color: "#14b8a6",
},
Mindset: {
icon: Brain,
color: "#E4E4E7",
},
} as const;

export const RemindersCard = () => {
const [reminderText, setReminderText] = useState("");
const [selectedType, setSelectedType] = useState<ReminderType>("Gratitude");

const reminderPlaceholders: Record<ReminderType, string> = {
Gratitude:
"\"I'm grateful for my family's unwavering support through everything.\"",
Motivation:
'"I will become a successful entrepreneur and make a positive impact."',
Affirmation:
'"I am capable of learning and growing beyond my current limitations."',
Challenge:
'"I will overcome my fear of public speaking and become a confident communicator."',
Dream:
'"My dream is to travel to all continents and experience diverse cultures."',
Mindset:
'"I choose to see obstacles as opportunities for growth and learning."',
};

const types = Object.keys(typeStyles) as ReminderType[];

const ReminderPreview = () => {
const { icon: Icon, color } = typeStyles[selectedType];

return (
<div
className="relative flex-col gap-4 rounded-3xl border-[1px] bg-[#0c0e12] p-3 text-[#d0dbe3] md:p-4"
style={{
borderColor: `${color}80`,
}}
>
<div className="mb-1 flex items-center gap-1">
<Icon size={20} color={color} weight="duotone" />
<p className="text-xs font-semibold" style={{ color }}>
{selectedType}
</p>
</div>
<p className="text-sm md:text-base">
{reminderText || reminderPlaceholders[selectedType]}
</p>
</div>
);
};

return (
<div className="flex w-full flex-col gap-8">
<div className="mx-auto w-full max-w-md">
<ReminderPreview />
</div>

<div className="space-y-4 rounded-2xl border-[1px] border-accent/60 bg-accent-foreground p-4">
<RadioGroup
className="grid grid-cols-3 gap-2 md:flex"
value={selectedType}
onValueChange={(value) => setSelectedType(value as ReminderType)}
>
{types.map((type) => (
<label
key={type}
className="w-fit cursor-pointer items-center justify-center rounded-2xl border-[1px] border-accent/60 p-2 text-xs text-muted-foreground transition-colors hover:bg-accent-foreground has-[[data-state=checked]]:border-secondary has-[[data-state=checked]]:bg-secondary-smooth-700/10 has-[[data-state=checked]]:text-secondary"
>
<RadioGroupItem
value={type}
className="sr-only after:absolute after:inset-0"
/>
<p className="font-medium leading-none">{type}</p>
</label>
))}
</RadioGroup>

<div className="flex w-full justify-between">
<Textarea
maxLength={140}
placeholder={reminderPlaceholders[selectedType]}
value={reminderText}
onChange={(e) => setReminderText(e.target.value)}
className="md:text-md mt-2 w-full text-sm"
rows={3}
/>
</div>
</div>
</div>
);
};

export default RemindersCard;
10 changes: 6 additions & 4 deletions src/components/landing-page/Features.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import {
CarouselItem,
} from "@/components/ui/carousel";
import type { CarouselApi } from "@/components/ui/carousel";
import { AmbientSoundCard } from "./FeatureFunctions";
import { AmbientSoundCard } from "./Cards/AmbientSoundCard";
import RemindersCard from "./Cards/RemindersCard";
import QuoteCard from "./Cards/QuoteCard";

const features = [
{
Expand All @@ -30,13 +32,13 @@ const features = [
title: "Grateful reminders",
description:
"Create custom reminders to pause and reflect on what matters most to you.",
component: () => <div>Reminders Component Placeholder</div>,
component: RemindersCard,
},
{
id: 4,
title: "Words That Resonate",
title: "Words That resonate",
description: "Find your daily spark with hand-picked quotes.",
component: () => <div>Quotes Component Placeholder</div>,
component: QuoteCard,
},
{
id: 5,
Expand Down

0 comments on commit da72e88

Please sign in to comment.