Skip to content

Commit

Permalink
feat: added tide visual display
Browse files Browse the repository at this point in the history
  • Loading branch information
ajesuscode committed Oct 25, 2023
1 parent df8bbc7 commit 1da3a34
Show file tree
Hide file tree
Showing 9 changed files with 730 additions and 21 deletions.
308 changes: 308 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"postcss": "8.4.27",
"react": "18.2.0",
"react-dom": "18.2.0",
"recharts": "^2.9.0",
"supabase": "^1.86.0",
"tailwindcss": "3.3.3",
"typescript": "5.1.6",
Expand Down
18 changes: 3 additions & 15 deletions src/app/(surfspots)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import Link from "next/link";

//utils
import { getTidesData, getCurrentTide } from "../utils/surfUtils";
import { FallinTideIcon, RisingTideIcon } from "../components/icons/icons";
import CurrentTide from "../components/atom/CurrentTide";

export default async function FavoriteSpotsLayout({
children,
}: {
Expand Down Expand Up @@ -50,20 +51,7 @@ export default async function FavoriteSpotsLayout({
</div>
</Link>
</div>

<div className="flex flex-row gap-0 justify-start items-center bg-dark/50 rounded-sm p-2">
{currentTide?.tide === "rising" ? (
<RisingTideIcon size={20} color="text-light/50" />
) : (
<FallinTideIcon size={20} color="text-light/50" />
)}
<span className="text-light/50 font-body text-sm pr-2">
{currentTide?.tide || null}
</span>
<span className="text-light/50 font-body text-sm">
{currentTide?.time || null}
</span>
</div>
<CurrentTide currentTide={currentTide} />
</div>
{children}
</main>
Expand Down
5 changes: 5 additions & 0 deletions src/app/(surfspots)/spots/[spot_id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { PintxoRange } from "@/app/components/PintxoRange";
import { getCurrentPintxoConditions } from "@/app/utils/surfUtils";
import { DateTime } from "luxon";
import SpotConditionsWeek from "@/app/components/SpotConditionsWeek";
import TideContainer from "@/app/components/atom/TideContainer";

async function getUser(): Promise<User | null> {
const supabase = createServerComponentClient<Database>({ cookies });
Expand Down Expand Up @@ -90,6 +91,10 @@ export default async function SpotPage({
))}
</div>
</div>
<div className="font-body text-secondary p-1 rounded-sm text-xs mt-2">
Tide
</div>
<TideContainer />
<div className="font-body text-secondary p-1 rounded-sm text-xs mt-2">
Detailed Weekly Conditions
</div>
Expand Down
27 changes: 27 additions & 0 deletions src/app/components/atom/CurrentTide.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"use client";
import React, { useState } from "react";
import { RisingTideIcon, FallinTideIcon } from "../icons/icons";

interface CurrentTideProps {
currentTide: { tide: string; time: string } | null;
}

const CurrentTide = ({ currentTide }: CurrentTideProps) => {
return (
<div className="flex flex-row gap-0 justify-start items-center bg-dark/50 rounded-sm p-2">
{currentTide?.tide === "rising" ? (
<RisingTideIcon size={20} color="text-light/50" />
) : (
<FallinTideIcon size={20} color="text-light/50" />
)}
<span className="text-light/50 font-body text-sm pr-2">
{currentTide?.tide || null}
</span>
<span className="text-light/50 font-body text-sm">
{currentTide?.time || null}
</span>
</div>
);
};

export default CurrentTide;
30 changes: 30 additions & 0 deletions src/app/components/atom/TideContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from "react";
import { DateTime } from "luxon";
import { getTidesData } from "@/app/utils/surfUtils";
import TideVisualGraph from "./TideVisualGraph";

type TidesType = {
height: number;
id: number;
time: number;
type: string;
};

const TideContainer = async () => {
const tidesData = await getTidesData();
let newTides: TidesType[] = [];
if (tidesData) {
newTides = tidesData.map((item) => ({
...item,
time: DateTime.fromISO(item.time).toMillis(),
}));
}

return (
<>
<TideVisualGraph tides={newTides} />
</>
);
};

export default TideContainer;
117 changes: 117 additions & 0 deletions src/app/components/atom/TideVisualGraph.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
"use client";
import React from "react";
import { DateTime } from "luxon";
import { getTidesData } from "@/app/utils/surfUtils";
import {
LineChart,
Line,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
Label,
ReferenceLine,
Area,
AreaChart,
} from "recharts";

interface TideVisualGraphProps {
tides: {
height: number;
id: number;
time: number;
type: string;
}[];
}

const TideVisualGraph = ({ tides }: TideVisualGraphProps) => {
let isMobile = false;
if (typeof window !== "undefined") {
const screenWidth = window.screen.width;
if (screenWidth < 768) {
isMobile = true;
}
}

const firstDayTides = tides.slice(0, 5).map((tide) => {
if (tide.height < 0) {
return { ...tide, height: 0.2 };
} else if (tide.height > 0) {
return { ...tide, height: 1 };
} else {
return tide;
}
});

const startHour = DateTime.fromMillis(firstDayTides[0].time).startOf(
"hour"
);
const endHour = DateTime.fromMillis(
firstDayTides[firstDayTides.length - 1].time
).endOf("hour");

const currentTime = DateTime.local().toMillis();

const hourlyTimestamps: number[] = [];

for (
let hour = startHour;
hour <= endHour;
hour = hour.plus({ hours: 1 })
) {
hourlyTimestamps.push(hour.toMillis());
}

return (
<div className="p-4 bg-light/20 rounded-md">
<ResponsiveContainer
width="100%"
height={120}
style={{ marginTop: 20 }}
>
<AreaChart
data={firstDayTides}
margin={{ top: 5, right: 10, left: 10, bottom: 0 }}
>
<XAxis
dataKey="time"
scale="time"
type="number"
domain={["auto", "auto"]}
ticks={hourlyTimestamps}
tick={{
stroke: "#c7d2fe",
strokeWidth: 1,
fontSize: 8,
}}
tickFormatter={
(time) => DateTime.fromMillis(time).toFormat("HH") // This will output just the hour part
}
interval={isMobile ? 2 : 1}
tickLine={false}
tickSize={5}
style={{ stroke: "#84cc16" }}
></XAxis>
<YAxis type="number" hide={true} dataKey="height" />

{/* Add Area below Line */}
<Area
type="monotone"
dataKey="height"
fill="#1e1b4b"
stroke="#1e1b4b"
/>
<ReferenceLine
x={currentTime}
stroke="#84cc16"
strokeWidth={5}
ifOverflow="extendDomain"
/>
</AreaChart>
</ResponsiveContainer>
</div>
);
};

export default TideVisualGraph;
2 changes: 2 additions & 0 deletions src/app/info/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react";
import pintxosData from "@/app/constants/pintxosData";
import Image from "next/image";
import Link from "next/link";
import TideContainer from "../components/atom/TideContainer";

const Info = () => {
return (
Expand All @@ -22,6 +23,7 @@ const Info = () => {
There are six surf conditions with corresponding pintxo name and
brand color. You can learn them below.
</p>
<TideContainer />

<div className="grid grid-cols-1 md:grid-cols-3 gap-4 h-full my-8">
{pintxosData.map((item, index) => (
Expand Down
Loading

0 comments on commit 1da3a34

Please sign in to comment.