-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Gabor Juhasz
committed
Jul 8, 2022
1 parent
dcd0d38
commit 2e5a7f7
Showing
13 changed files
with
338 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { Filter } from "pages"; | ||
import React, { FC, useRef } from "react"; | ||
import { Location, Program, Range } from "types"; | ||
|
||
interface FormProps { | ||
filter: Filter; | ||
setFilter: (filter: Filter) => void; | ||
} | ||
export const Form: FC<FormProps> = ({ filter, setFilter }) => { | ||
const formRef = useRef<HTMLFormElement>(null); | ||
const onChange = React.useCallback(() => { | ||
if (!formRef.current) { | ||
return; | ||
} | ||
const data = new FormData(formRef.current); | ||
setFilter({ | ||
range: data.get("range") as Range, | ||
program: data.getAll("program") as Program[], | ||
location: data.getAll("location") as Location[], | ||
}); | ||
}, [setFilter]); | ||
|
||
return ( | ||
<form ref={formRef}> | ||
<div> | ||
{Object.values(Location).map((location) => { | ||
return ( | ||
<input | ||
key={location} | ||
type="checkbox" | ||
name="location" | ||
value={location} | ||
checked={filter.location?.includes(location)} | ||
onChange={onChange} | ||
/> | ||
); | ||
})} | ||
</div> | ||
|
||
<div> | ||
{Object.values(Program).map((program) => { | ||
return ( | ||
<input | ||
key={program} | ||
type="checkbox" | ||
name="program" | ||
value={program} | ||
checked={filter.program?.includes(program)} | ||
onChange={onChange} | ||
/> | ||
); | ||
})} | ||
</div> | ||
|
||
<div> | ||
{Object.values(Range).map((range) => { | ||
return ( | ||
<input | ||
key={range} | ||
type="radio" | ||
name="range" | ||
value={range} | ||
checked={range === filter.range} | ||
onChange={onChange} | ||
/> | ||
); | ||
})} | ||
</div> | ||
</form> | ||
); | ||
}; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
import '../styles/globals.css' | ||
import type { AppProps } from 'next/app' | ||
import "styles/globals.css"; | ||
import type { AppProps } from "next/app"; | ||
|
||
function MyApp({ Component, pageProps }: AppProps) { | ||
return <Component {...pageProps} /> | ||
return <Component {...pageProps} />; | ||
} | ||
|
||
export default MyApp | ||
export default MyApp; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import type { NextApiRequest, NextApiResponse } from "next"; | ||
import { Range, Location, Program, Item } from "types"; | ||
import dayjs from "dayjs"; | ||
|
||
const getUrl = (host?: string) => { | ||
if (!host) { | ||
return; | ||
} | ||
const protocol = host.includes("localhost") ? "http://" : "https://"; | ||
return protocol + host; | ||
}; | ||
|
||
const normalizeQueryValue = (value: string | string[] | undefined): any[] | undefined => { | ||
if (typeof value === "string") { | ||
return value.split(","); | ||
} | ||
return value; | ||
}; | ||
|
||
export default async function handler(req: NextApiRequest, res: NextApiResponse) { | ||
const response = await fetch(getUrl(req.headers.host) + "/api"); | ||
if (!response.ok) { | ||
res.status(response.status).end(); | ||
return; | ||
} | ||
|
||
const data = await response.json(); | ||
let list: Item[] = data.data.centerpiece; | ||
list = list.map((item, index) => { | ||
item.id = index; | ||
return item; | ||
}); | ||
|
||
list = filterByLocation(list, normalizeQueryValue(req.query.location)); | ||
list = filterByProgram(list, normalizeQueryValue(req.query.program)); | ||
list = filterByRange(list, req.query.range as Range); | ||
res.json(list); | ||
} | ||
|
||
const filterByLocation = (list: Item[], locations: Location[] | undefined) => { | ||
if (!locations) { | ||
return list; | ||
} | ||
return list.filter((item) => { | ||
if (!item.village) { | ||
return true; | ||
} | ||
return locations.some((location) => location === item.village?.name); | ||
}); | ||
}; | ||
|
||
const filterByProgram = (list: Item[], programs: Program[] | undefined) => { | ||
if (!programs) { | ||
return list; | ||
} | ||
return list.filter((item) => { | ||
if (!item.labels) { | ||
return true; | ||
} | ||
return programs.some((program) => { | ||
const labelNames = item.labels?.map((label) => label.name); | ||
return labelNames?.includes(program); | ||
}); | ||
}); | ||
}; | ||
|
||
const parseDate = (item: Item) => { | ||
return new Date("2022 " + item.time?.name).getTime() / 1000; | ||
}; | ||
|
||
const getDateForRange = (range: Range): number => { | ||
switch (range) { | ||
case Range.three: { | ||
return dayjs().add(3, "hours").unix(); | ||
} | ||
case Range.today: { | ||
return dayjs().endOf("day").unix(); | ||
} | ||
case Range.tomorrow: { | ||
return dayjs().add(1, "day").endOf("day").unix(); | ||
} | ||
default: { | ||
return 0; | ||
} | ||
} | ||
}; | ||
|
||
const filterByRange = (list: Item[], range: Range) => { | ||
if (range === Range.all) { | ||
return list; | ||
} | ||
const rangeDate = getDateForRange(range); | ||
return list.filter((item) => { | ||
const date = parseDate(item); | ||
return date < rangeDate; | ||
}); | ||
}; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import type { NextApiRequest, NextApiResponse } from "next"; | ||
import jsonData from "data.json"; | ||
|
||
const URL = "https://ordogkatlan.hu/2022"; | ||
|
||
export default async function handler(req: NextApiRequest, res: NextApiResponse) { | ||
res.json(jsonData); | ||
return; | ||
|
||
console.log("fetching " + URL); | ||
const response = await fetch(URL, { | ||
headers: { Accept: "application/json" }, | ||
}); | ||
|
||
if (!response.ok) { | ||
res.status(response.status).end(); | ||
return; | ||
} | ||
|
||
const data = await response.json(); | ||
res.setHeader("Cache-Control", "public, s-maxage=3600, stale-while-revalidate"); | ||
res.json(data); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,51 @@ | ||
import type { NextPage } from 'next' | ||
import Head from 'next/head' | ||
import Image from 'next/image' | ||
import styles from '../styles/Home.module.css' | ||
import { Form } from "components/Form"; | ||
import type { NextPage } from "next"; | ||
import React, { useEffect, useState } from "react"; | ||
import { useLocalStorage } from "utils/useLocalStorage"; | ||
import { Location, Program, Range, Item } from "types"; | ||
|
||
export interface Filter { | ||
range: Range; | ||
program?: Program[]; | ||
location?: Location[]; | ||
} | ||
|
||
const Home: NextPage = () => { | ||
return ( | ||
<div className={styles.container}> | ||
<Head> | ||
<title>Create Next App</title> | ||
<meta name="description" content="Generated by create next app" /> | ||
<link rel="icon" href="/favicon.ico" /> | ||
</Head> | ||
|
||
<main className={styles.main}> | ||
<h1 className={styles.title}> | ||
Welcome to <a href="https://nextjs.org">Next.js!</a> | ||
</h1> | ||
|
||
<p className={styles.description}> | ||
Get started by editing{' '} | ||
<code className={styles.code}>pages/index.tsx</code> | ||
</p> | ||
|
||
<div className={styles.grid}> | ||
<a href="https://nextjs.org/docs" className={styles.card}> | ||
<h2>Documentation →</h2> | ||
<p>Find in-depth information about Next.js features and API.</p> | ||
</a> | ||
const [filter, setFilter] = useLocalStorage<Filter>("DD_KATLAN_FILTER", { | ||
range: Range.all, | ||
program: Object.values(Program), | ||
location: Object.values(Location), | ||
}); | ||
const [list, setList] = useState<Item[]>([]); | ||
|
||
useEffect(() => { | ||
// @ts-ignore | ||
const query = new URLSearchParams(filter); | ||
// console.log(filter, query.toString()); | ||
fetch("/api/filter?" + query) | ||
.then((r) => r.json()) | ||
.then((r) => setList(r)); | ||
}, [filter]); | ||
|
||
<a href="https://nextjs.org/learn" className={styles.card}> | ||
<h2>Learn →</h2> | ||
<p>Learn about Next.js in an interactive course with quizzes!</p> | ||
</a> | ||
|
||
<a | ||
href="https://github.com/vercel/next.js/tree/canary/examples" | ||
className={styles.card} | ||
> | ||
<h2>Examples →</h2> | ||
<p>Discover and deploy boilerplate example Next.js projects.</p> | ||
</a> | ||
|
||
<a | ||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app" | ||
className={styles.card} | ||
> | ||
<h2>Deploy →</h2> | ||
<p> | ||
Instantly deploy your Next.js site to a public URL with Vercel. | ||
</p> | ||
</a> | ||
</div> | ||
</main> | ||
|
||
<footer className={styles.footer}> | ||
<a | ||
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
> | ||
Powered by{' '} | ||
<span className={styles.logo}> | ||
<Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} /> | ||
</span> | ||
</a> | ||
</footer> | ||
return ( | ||
<div> | ||
<h1>{list.length}</h1> | ||
{list.map((item) => ( | ||
<li key={item.id}>{item.title}</li> | ||
))} | ||
|
||
<div | ||
style={{ | ||
width: "100%", | ||
background: "white", | ||
position: "fixed", | ||
bottom: 0, | ||
}} | ||
> | ||
<Form filter={filter} setFilter={setFilter} /> | ||
</div> | ||
</div> | ||
) | ||
} | ||
); | ||
}; | ||
|
||
export default Home | ||
export default Home; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.