Skip to content

Commit

Permalink
Add previous dreams display
Browse files Browse the repository at this point in the history
  • Loading branch information
bombies committed Oct 28, 2023
1 parent 5799d09 commit 6f08b60
Show file tree
Hide file tree
Showing 13 changed files with 295 additions and 80 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const DreamCard: FC<Props> = ({dream, optimisticRemove}) => {
onDelete={() => {
if (optimisticRemove)
optimisticRemove(
doDelete, // TODO: Replace with API call
doDelete,
dream
)
.then(() => {
Expand All @@ -57,7 +57,7 @@ const DreamCard: FC<Props> = ({dream, optimisticRemove}) => {
footer: "bg-[#0C0015] px-8",
}}>
<CardHeader className="flex justify-between">
<h2 className="text-3xl tablet:text-xl font-semibold whitespace-nowrap overflow-hidden overflow-ellipsis max-w-[80%] phone:max-w-[50%]">{dream.title}</h2>
<h2 className="text-3xl tablet:text-xl font-semibold whitespace-nowrap overflow-hidden overflow-ellipsis max-w-[80%] tablet:max-w-[70%] phone:max-w-[50%]">{dream.title}</h2>
<p className="text-subtext text-lg self-end">
{new Date(dream.createdAt.toString()).toLocaleTimeString("en-US", {
timeStyle: 'short'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {FC, Fragment, useMemo} from "react";
import {useDreamsData} from "@/app/(site)/(internal)/dashboard/components/dreams/DreamsProvider";
import DreamCard from "@/app/(site)/(internal)/dashboard/components/dreams/card/DreamCard";
import LogDreamCard from "@/app/(site)/(internal)/dashboard/components/dreams/LogDreamCard";
import useTodayTimeRange from "@/app/(site)/hooks/time-hooks";
import DreamCardSkeleton from "@/app/(site)/(internal)/dashboard/components/dreams/card/DreamCardSkeleton";
import DreamContainer from "@/app/(site)/(internal)/dashboard/components/dreams/containers/DreamContainer";

const CurrentDreamsContainer: FC = () => {
const [startOfToday, endOfToday] = useTodayTimeRange()
const {dreams} = useDreamsData()
const dreamCards = useMemo(() => dreams.data
.filter(dream => {
const creationDate = new Date(dream.createdAt.toString());
return creationDate >= startOfToday && creationDate <= endOfToday
})
.sort((a, b) => new Date(b.createdAt.toString()).getTime() - new Date(a.createdAt.toString()).getTime())
.map(dream => (
<DreamCard
key={dream.id}
dream={dream}
optimisticRemove={dreams.optimisticData.removeOptimisticData}
/>
)), [dreams.data, dreams.optimisticData.removeOptimisticData, endOfToday, startOfToday])

return (
<DreamContainer title={`Today
- ${
startOfToday.toLocaleDateString("en-US", {
dateStyle: "medium"
})
}`}>
<LogDreamCard/>
{dreams.loading ? (
<Fragment>
<DreamCardSkeleton/>
<DreamCardSkeleton/>
<DreamCardSkeleton/>
</Fragment>
) : (dreamCards.length ? dreamCards :
<h3 className="text-center font-light text-3xl tablet:text-xl text-subtext/30 py-6">You have no
dreams today...</h3>)
}
</DreamContainer>
)
}

export default CurrentDreamsContainer
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {FC, PropsWithChildren} from "react";
import clsx from "clsx";

type Props = {
title: string,
className?: string,
containerClassName?: string,
} & PropsWithChildren

const DreamContainer: FC<Props> = ({title, children, className, containerClassName}) => {
return (
<div className={clsx(className, "flex flex-col")}>
<h2 className="text-4xl phone:text-2xl font-semibold mb-8 phone:mb-4 tablet:text-center">{title}</h2>
<div
className={clsx(
containerClassName,
"bg-primary/20 rounded-3xl py-6 px-4 phone:p-3 w-[36rem] tablet:w-[24rem] phone:w-[20rem] tablet:self-center flex flex-col gap-y-6 phone:gap-y-3"
)}>
{children}
</div>
</div>
)
}

export default DreamContainer
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"use client"

import {FC, Fragment, useMemo} from "react";
import {PastDream} from "@/app/(site)/(internal)/dashboard/components/dreams/containers/PastDreamsContainer";
import DreamCard from "@/app/(site)/(internal)/dashboard/components/dreams/card/DreamCard";

type Props = {
dream: PastDream
}

const PastDreamItem: FC<Props> = ({dream}) => {
const cards = useMemo(() => dream.dreams.map(pastDream => (
<DreamCard key={pastDream.id} dream={pastDream} />
)), [dream.dreams])

return (
<Fragment>
<h3 className="text-center font-semibold phone:font-normal text-xl phone:text-medium">{new Date(dream.timestamp).toLocaleString("en-US", {
dateStyle: "full"
})}</h3>
{cards}
</Fragment>
)
}

export default PastDreamItem
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
"use client"

import {FC, Fragment, useMemo} from "react";
import DreamContainer from "@/app/(site)/(internal)/dashboard/components/dreams/containers/DreamContainer";
import {useDreamsData} from "@/app/(site)/(internal)/dashboard/components/dreams/DreamsProvider";
import {Dream} from "@prisma/client";
import {useStartOfDay} from "@/app/(site)/hooks/time-hooks";
import PastDreamItem from "@/app/(site)/(internal)/dashboard/components/dreams/containers/PastDreamItem";
import DreamCardSkeleton from "@/app/(site)/(internal)/dashboard/components/dreams/card/DreamCardSkeleton";
import {Divider} from "@nextui-org/divider";
import Card from "@/app/(site)/components/Card";
import Link from "next/link";
import {CardBody} from "@nextui-org/card";
import {useRouter} from "next/navigation";
import PillowIcon from "@/app/(site)/components/icons/PillowIcon";
import CloudIcon from "@/app/(site)/components/icons/CloudIcon";

type GroupedDreams = {
[K: string]: Dream[]
}

export type PastDream = {
timestamp: number,
dreams: Dream[]
}

const NUMBER_OF_DAYS = 7

const PastDreamsContainer: FC = () => {
const router = useRouter()
const {dreams} = useDreamsData()
const earliestDate = useStartOfDay({
dayOffset: -NUMBER_OF_DAYS, // A week ago @ 12:00 AM
})

const pastDreams = useMemo<PastDream[]>(() => {
const filteredDreams = dreams.data.filter(dream => new Date(dream.createdAt.toString()).getTime() >= earliestDate.getTime())
const dayTimes = [earliestDate]
for (let i = 1; i < NUMBER_OF_DAYS; i++) {
const d = new Date(dayTimes[dayTimes.length - 1])
d.setTime(d.getTime() + (24 * 60 * 60 * 1000))
dayTimes.push(d)
}

const groupedDreams = dayTimes.reduce<GroupedDreams>((previousValue, currentValue, i, arr) => {
const endDate = new Date(arr[i])
endDate.setHours(11, 59, 59, 999)

const dreams = filteredDreams.filter(dream => {
const dreamDate = new Date(dream.createdAt)
return dreamDate >= currentValue && dreamDate <= endDate
})

return ({
...previousValue,
[currentValue.getTime()]: dreams
})
}, {})

const pastDreamsArr: PastDream[] = []
for (let timestamp in groupedDreams) {
const dreamsForDay = groupedDreams[timestamp]
if (dreamsForDay.length === 0)
continue
pastDreamsArr.push({
timestamp: Number(timestamp),
dreams: dreamsForDay
})
}

return pastDreamsArr.sort((a, b) => b.timestamp - a.timestamp)
}, [dreams.data, earliestDate])


const dreamItems = useMemo(() => pastDreams.map(dream => (
<PastDreamItem
key={dream.timestamp}
dream={dream}
/>
)), [pastDreams])


return (
<DreamContainer
containerClassName="!py-12"
title="Previous Dreams"
>
{dreams.loading ? (
<Fragment>
<DreamCardSkeleton/>
<DreamCardSkeleton/>
<DreamCardSkeleton/>
</Fragment>
) : (dreamItems.length ?
<Fragment>
{dreamItems}
<Divider className="my-3" />
<Card
onPress={() => router.push("/dashboard/calendar")}
isPressable
isBlurred
classNames={{
base: "hover:scale-105",
body: "bg-secondary py-8"
}}
>
<CardBody>
<div className="flex gap-4">
<CloudIcon width={32} />
<p className="font-semibold text-lg phone:text-medium self-center">View All Dreams</p>
</div>
</CardBody>
</Card>
</Fragment>
:
<h3 className="text-center font-light text-3xl tablet:text-xl text-subtext/30 py-6">You have no
dreams today...</h3>)
}
</DreamContainer>
)
}

export default PastDreamsContainer
6 changes: 4 additions & 2 deletions src/app/(site)/(internal)/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
"use client"

import {FC, Fragment} from "react";
import CurrentDreamsContainer from "@/app/(site)/(internal)/dashboard/components/dreams/CurrentDreamsContainer";
import CurrentDreamsContainer from "@/app/(site)/(internal)/dashboard/components/dreams/containers/CurrentDreamsContainer";
import PastDreamsContainer from "@/app/(site)/(internal)/dashboard/components/dreams/containers/PastDreamsContainer";

const DashboardHomePage: FC = () => {
return (
<Fragment>
<h1 className="font-bold text-7xl phone:text-5xl mb-24 phone:mb-10">Your Dreams</h1>
<div className="flex flex-wrap laptop:flex-col laptop:items-center gap-24 laptop-min:gap-12">
<CurrentDreamsContainer />
<CurrentDreamsContainer/>
<PastDreamsContainer/>
</div>
</Fragment>
)
Expand Down
18 changes: 18 additions & 0 deletions src/app/(site)/components/icons/PillowIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as React from "react"
import {IconProps} from "@/app/(site)/components/icons/icon-utils";
import clsx from "clsx";

const PillowIcon = ({ className, fill, width, height }: IconProps) => (
<svg
xmlns="http://www.w3.org/2000/svg"
className={clsx("self-center", className)}
width={width ?? 24}
height={height ?? width ?? 24}
viewBox="0 0 50 50"
>
<path
fill={clsx(fill ?? "currentColor")}
d="M48.87 41.175c.02.19.03.38.01.57v.01c-.03.4-.12.8-.34 1.15-.09.16-.2.3-.34.44-1.49 1.46-4.2.68-6.83-.07l-.64-.19c-.93-.26-2.12-.39-3.73-.4-.73 0-1.5.02-2.3.05-.81.03-1.66.07-2.54.12-1.99.1-4.24.21-6.63.21h-1.06c-2.38 0-4.64-.11-6.63-.21-3.51-.18-6.55-.34-8.57.23l-.64.19c-1.54.44-3.12.89-4.46.89-.94 0-1.76-.22-2.37-.82-1.24-1.23-.62-3.23-.17-4.69.1-.34.2-.65.25-.9.12-.59.3-1.19.47-1.76.05-.16.09-.31.14-.47 1.06 1.33 2.39 2.55 4.01 3.47.16.09.33.13.5.13.35 0 .68-.18.87-.5.27-.48.11-1.09-.37-1.37-2.54-1.45-4.27-3.76-5.3-5.9-.01-.02-.01-.03-.02-.04-1.12-2.92-1.18-5.68-1.18-6.19 0-3.06.37-5.7.67-7.81.25-1.76.45-3.15.34-4.07-.08-.63-.26-1.32-.43-1.99-.41-1.62-.84-3.29.22-4.34 1.47-1.47 4.18-.69 6.81.06l1.24.35c.64.19 1.49.43 2.38.64-1.84 1.07-3.62 2.55-5.05 4.59a.99.99 0 0 0 .25 1.39c.17.12.37.18.57.18.31 0 .62-.15.82-.43 3.15-4.49 8.26-5.92 11.49-6.37.04 0 .08-.01.12-.01 1.5-.14 2.79-.13 3.67-.13h1.43c2.38 0 4.64.11 6.63.21 3.51.18 6.55.33 8.57-.23l.66-.19c2.63-.75 5.34-1.53 6.81-.06 1.06 1.05.63 2.72.22 4.34-.17.67-.35 1.36-.43 1.99-.11.92.09 2.31.34 4.07.3 2.11.67 4.75.67 7.81 0 2.13-.68 6.63-1.15 9.66-.91-1.4-1.85-2.97-1.85-3.66 0-.55-.45-1-1-1s-1 .45-1 1c0 1.39 1.21 3.33 2.93 5.91.68 1.02 1.695 2.715 1.94 4.13v.01z"/>
</svg>
)
export default PillowIcon
48 changes: 48 additions & 0 deletions src/app/(site)/hooks/time-hooks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"use client"

import {useMemo} from "react";

const useTodayTimeRange = () => {
return useDayTimeRange()
}

type DayTimeArgs = {
date?: Date,
dayOffset?: number
}

export const useStartOfDay = (options?: DayTimeArgs) => {
return useMemo(() => {
const d = options?.date ? new Date(options.date) : new Date()
d.setHours(0, 0, 0, 0)

if (options?.dayOffset)
d.setTime(d.getTime() + (options.dayOffset * 24 * 60 * 60 * 1000))
return d;
}, [options?.date, options?.dayOffset])
}

export const useEndOfDay = (options?: DayTimeArgs) => {
return useMemo(() => {
const d = options?.date ? new Date(options.date) : new Date()
d.setHours(23, 59, 59, 999)

if (options?.dayOffset)
d.setTime(d.getTime() + (options.dayOffset * 24 * 60 * 60 * 1000))
return d;
}, [options?.date, options?.dayOffset])
}

type DayTimeRangeArgs = Partial<{
date: Date,
startDayOffset: number
endDayOffset: number
}>

export const useDayTimeRange = (options?: DayTimeRangeArgs): [Date, Date] => {
const startOfDay = useStartOfDay({date: options?.date, dayOffset: options?.startDayOffset})
const endOfDay = useEndOfDay({date: options?.date, dayOffset: options?.endDayOffset})
return [startOfDay, endOfDay]
}

export default useTodayTimeRange
Loading

0 comments on commit 6f08b60

Please sign in to comment.