Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added search functionality #15

Merged
merged 1 commit into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"extends": "next/core-web-vitals"
"extends": "next/core-web-vitals"
}
13 changes: 13 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@types/node": "20.4.9",
"@types/react": "18.2.20",
"@types/react-dom": "18.2.7",
"@uidotdev/usehooks": "^2.4.1",
"airtable": "^0.12.1",
"autoprefixer": "10.4.14",
"encoding": "^0.1.13",
Expand Down
2 changes: 0 additions & 2 deletions src/app/(surfspots)/favorite/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { createServerComponentClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import { fetchSpotSurfData } from "@/app/utils/surfUtils";
import { FullSpot, SurfSpot, FavoriteSpot } from "@/app/constants/types";
import Link from "next/link";

//Components
Expand Down
38 changes: 22 additions & 16 deletions src/app/(surfspots)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { redirect } from "next/navigation";
import { cookies } from "next/headers";
import type { Database } from "../lib/database.types";
import Link from "next/link";
import SearchPintxos from "../components/atom/SearchPintxos";

//utils
import { getTidesData, getCurrentTide } from "../utils/surfUtils";
Expand All @@ -27,31 +28,36 @@ export default async function FavoriteSpotsLayout({
return (
<main className="flex flex-col p-4 pt-16 xl:p-20 h-full">
<div className="flex flex-row justify-between gap-4 items-center sticky top-14 bg-primary py-4 z-20 w-full">
<div className="flex flex-row gap-4 justify-start ">
{user && (
<Link href="/favorite">
<div className="flex flex-col md:flex-row gap-4 justify-between items-center w-full">
<div className="flex flex-row justify-start items-center gap-4 w-full">
{user && (
<Link href="/favorite">
<div
className={`font-body text-base lg:text-xl font-bold
text-light/50

`}
>
Favorite
</div>
</Link>
)}
<Link href="/spots">
<div
className={`font-body text-base lg:text-xl font-bold
text-light/50

`}
>
Favorite
All Pintxos
</div>
</Link>
)}
<Link href="/spots">
<div
className={`font-body text-base lg:text-xl font-bold
text-light/50

`}
>
All Pintxos
</div>
</Link>
</div>
<div className="flex flex-row gap-4 justify-end items-center">
<SearchPintxos />
<CurrentTide currentTide={currentTide} />
</div>
</div>
<CurrentTide currentTide={currentTide} />
</div>
{children}
</main>
Expand Down
2 changes: 1 addition & 1 deletion src/app/(surfspots)/spots/SpotsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default async function SpotsList() {

return (
<>
<div className="grid grid-cols-1 gap-8 lg:grid-cols-4 md:grid-cols-2 ">
<div className="grid grid-cols-1 gap-8 lg:grid-cols-4 md:grid-cols-2">
{allSpotsData &&
allSpotsData.map((spot) => {
if (spot) {
Expand Down
84 changes: 84 additions & 0 deletions src/app/components/atom/SearchPintxos.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"use client";
import { useState, useEffect } from "react";
import { createClientComponentClient } from "@supabase/auth-helpers-nextjs";
import type { Database } from "@/app/lib/database.types";
import Link from "next/link";
import { useClickAway } from "@uidotdev/usehooks";

type SpotConditions = Database["public"]["Tables"]["spot_conditions"]["Row"];

const SearchPintxos = () => {
const [pintxos, setPintxos] = useState<SpotConditions[] | null>(null);
const [search, setSearch] = useState<string>("");
const supabase = createClientComponentClient<Database>();
const ref = useClickAway(() => {
setPintxos(null);
setSearch("");
});

useEffect(() => {
async function searchPintxos() {
if (search.trim() === "") {
setPintxos(null);
return;
}
const { data, error } = await supabase
.from("spot_conditions")
.select("*")
.like("name", `%${search}%`);

if (error) {
console.log("ERROR", error.message);
}
setPintxos(data);
}
searchPintxos();
}, [search]);

const handlePintxoClick = (): void => {
setPintxos(null);
setSearch("");
};

console.log("SEARCH", search);
console.log("PINTXO", pintxos);

return (
<div className="">
<div
className="relative"
ref={ref as React.RefObject<HTMLDivElement>}
>
<input
type="text"
placeholder="Search pintxos"
value={search}
onChange={(e) => setSearch(e.target.value)}
className="border border-secondary/50 rounded-md p-2 !bg-transparent font-body text-md font-light text-secondary ring-0 focus:ring-secondary focus:outline-none"
/>
{pintxos && pintxos.length > 0 && (
<div className="absolute top-12 left-0 bg-light/100 rounded-md p-2 flex flex-col justify-start items-start gap-2 w-full">
{pintxos?.map((pintxo) => (
<div
key={pintxo.spot_id}
onClick={() => handlePintxoClick()}
className="w-full"
>
<Link
href={`/spots/${pintxo.spot_id}`}
className="flex flex-row justify-between items-center w-full"
>
<div className="text-dark font-body tracking-wider text-lg grow">
{pintxo.name}
</div>
</Link>
</div>
))}
</div>
)}
</div>
</div>
);
};

export default SearchPintxos;
35 changes: 1 addition & 34 deletions src/app/utils/surfUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,7 @@ import { createServerComponentClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import { DateTime } from "luxon";
//types
import {
FullSpot,
SurfSpot,
HourlySurfData,
FavoriteSpot,
TideType,
HourlyWeatherData,
ForecastDataResponse,
Pintxo,
} from "../constants/types";
import { TideType, Pintxo } from "../constants/types";
import { Database } from "../lib/database.types";
type PintxoConditions = Database["public"]["Tables"]["spot_conditions"]["Row"];
type WeekdayPintxoCondition = {
Expand Down Expand Up @@ -58,30 +49,6 @@ function getAverageDirection(direction: string): number {
return avgDirection;
}

export async function fetchSpotSurfData(spot: SurfSpot) {
const marineApiUrl = `https://marine-api.open-meteo.com/v1/marine?latitude=${spot.lat}&longitude=${spot.long}&hourly=wave_height,wave_direction,wave_period,swell_wave_height,swell_wave_direction,swell_wave_period`;
const forecastApiUrl = `https://api.open-meteo.com/v1/forecast?latitude=${spot.lat}&longitude=${spot.long}&hourly=temperature_2m,precipitation,visibility,windspeed_10m,winddirection_10m,temperature_80m,uv_index&models=best_match`;

const [marineResponse, forecastResponse] = await Promise.all([
fetch(marineApiUrl),
fetch(forecastApiUrl),
]);

if (!marineResponse.ok) {
throw new Error(`Failed to fetch data for spot ${spot.name}`);
}

const hourlySurfData: HourlySurfData = await marineResponse.json();
const forecastData: ForecastDataResponse = await forecastResponse.json();
const hourlyWeatherData: HourlyWeatherData = forecastData.hourly;

return {
...spot,
hourlySpotForecast: hourlySurfData,
hourlyWeatherData: hourlyWeatherData,
};
}

export function getCurrentWaveHeightForSpot(
spot: PintxoConditions
): string | null {
Expand Down
1 change: 0 additions & 1 deletion src/app/utils/uiUtils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
export function getPintxoColor(condition: string): string {
switch (condition) {
case "Empty Plate":
console.log("condition", condition);
return "bg-purple-400";
case "Bread Only":
return "bg-red-400";
Expand Down
53 changes: 27 additions & 26 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"noUnusedLocals": false,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
9 changes: 7 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,11 @@
"@typescript-eslint/types" "6.3.0"
eslint-visitor-keys "^3.4.1"

"@uidotdev/usehooks@^2.4.1":
version "2.4.1"
resolved "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.4.1.tgz"
integrity sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg==

abort-controller@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz"
Expand Down Expand Up @@ -2274,7 +2279,7 @@ queue-microtask@^1.2.2:
resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==

"react-dom@^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.0.0 || ^17.0.0 || ^18.0.0", react-dom@^18.2.0, react-dom@>=15.0.0, [email protected]:
"react-dom@^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.0.0 || ^17.0.0 || ^18.0.0", react-dom@^18.2.0, react-dom@>=15.0.0, react-dom@>=18.0.0, react-dom@18.2.0:
version "18.2.0"
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz"
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
Expand Down Expand Up @@ -2317,7 +2322,7 @@ [email protected]:
prop-types "^15.6.2"
react-lifecycles-compat "^3.0.4"

"react@^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react@^16.0.0 || ^17.0.0 || ^18.0.0", react@^18.2.0, "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", react@>=15.0.0, [email protected]:
"react@^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react@^16.0.0 || ^17.0.0 || ^18.0.0", react@^18.2.0, "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", react@>=15.0.0, react@>=18.0.0, react@18.2.0:
version "18.2.0"
resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
Expand Down
Loading