Compare commits
No commits in common. "f727ade53964de6791d2efd2700235deed46f5a0" and "4d5d7a0c08b25f08d68cee4c42f03da5ac667dfe" have entirely different histories.
f727ade539
...
4d5d7a0c08
9 changed files with 26 additions and 198 deletions
|
|
@ -1 +0,0 @@
|
||||||
ALTER TABLE "eventsTable" ADD COLUMN "location" text;
|
|
||||||
|
|
@ -1,131 +0,0 @@
|
||||||
{
|
|
||||||
"id": "f3f30a9d-d72d-4e62-86b4-031282707007",
|
|
||||||
"prevId": "c0102a7e-5d09-41ca-88d1-c66f2f299e65",
|
|
||||||
"version": "7",
|
|
||||||
"dialect": "postgresql",
|
|
||||||
"tables": {
|
|
||||||
"public.eventsTable": {
|
|
||||||
"name": "eventsTable",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"startTime": {
|
|
||||||
"name": "startTime",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"endTime": {
|
|
||||||
"name": "endTime",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"name": "name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"title": {
|
|
||||||
"name": "title",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"name": "description",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"type": {
|
|
||||||
"name": "type",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"location": {
|
|
||||||
"name": "location",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"lineId": {
|
|
||||||
"name": "lineId",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"eventsTable_lineId_linesTable_id_fk": {
|
|
||||||
"name": "eventsTable_lineId_linesTable_id_fk",
|
|
||||||
"tableFrom": "eventsTable",
|
|
||||||
"tableTo": "linesTable",
|
|
||||||
"columnsFrom": [
|
|
||||||
"lineId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"id"
|
|
||||||
],
|
|
||||||
"onDelete": "cascade",
|
|
||||||
"onUpdate": "cascade"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
},
|
|
||||||
"public.linesTable": {
|
|
||||||
"name": "linesTable",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "integer",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"name": "name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"name": "description",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"enums": {},
|
|
||||||
"schemas": {},
|
|
||||||
"sequences": {},
|
|
||||||
"roles": {},
|
|
||||||
"policies": {},
|
|
||||||
"views": {},
|
|
||||||
"_meta": {
|
|
||||||
"columns": {},
|
|
||||||
"schemas": {},
|
|
||||||
"tables": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -8,13 +8,6 @@
|
||||||
"when": 1750786732013,
|
"when": 1750786732013,
|
||||||
"tag": "0000_noisy_omega_red",
|
"tag": "0000_noisy_omega_red",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
},
|
|
||||||
{
|
|
||||||
"idx": 1,
|
|
||||||
"version": "7",
|
|
||||||
"when": 1751371464551,
|
|
||||||
"tag": "0001_magenta_naoko",
|
|
||||||
"breakpoints": true
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
"db-generate": "drizzle-kit generate"
|
"push-db": "drizzle-kit push"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@electric-sql/pglite": "^0.3.3",
|
"@electric-sql/pglite": "^0.3.3",
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,7 @@ export default async function Home({ searchParams }: HomePageProps) {
|
||||||
<li className="mb-2">
|
<li className="mb-2">
|
||||||
<a href="/now" className="text-blue-600 hover:underline">
|
<a href="/now" className="text-blue-600 hover:underline">
|
||||||
Kam jít?
|
Kam jít?
|
||||||
</a>{" "}
|
</a>
|
||||||
<span className="text-gray-500">(nejbližší 2 hodiny)</span>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -53,11 +52,6 @@ export default async function Home({ searchParams }: HomePageProps) {
|
||||||
month: "numeric",
|
month: "numeric",
|
||||||
})}
|
})}
|
||||||
</a>
|
</a>
|
||||||
<span className="text-gray-500">
|
|
||||||
{new Date(day).getDay() === new Date().getDay()
|
|
||||||
? " (dnes)"
|
|
||||||
: ""}
|
|
||||||
</span>
|
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,14 @@ export interface Line {
|
||||||
description: string;
|
description: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const userAgentHeader = {
|
|
||||||
"User-Agent":
|
|
||||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function getLines() {
|
export async function getLines() {
|
||||||
const annotation = await fetch(
|
const annotation = await fetch(
|
||||||
"https://amber.festivalfantazie.cz/porady.php",
|
"https://amber.festivalfantazie.cz/porady.php",
|
||||||
{
|
{
|
||||||
headers: userAgentHeader,
|
headers: {
|
||||||
|
"User-Agent":
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -70,14 +68,16 @@ export interface Event {
|
||||||
description: string;
|
description: string;
|
||||||
type: string;
|
type: string;
|
||||||
lineId: number;
|
lineId: number;
|
||||||
location?: string; // Optional location field
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getScheduleForLine(lineId: number) {
|
export async function getScheduleForLine(lineId: number) {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`https://amber.festivalfantazie.cz/program_linie.php?linie=${lineId}`,
|
`https://amber.festivalfantazie.cz/program_linie.php?linie=${lineId}`,
|
||||||
{
|
{
|
||||||
headers: userAgentHeader,
|
headers: {
|
||||||
|
"User-Agent":
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -162,7 +162,8 @@ export async function getScheduleForLine(lineId: number) {
|
||||||
"https://amber.festivalfantazie.cz/ajax/anotace.php",
|
"https://amber.festivalfantazie.cz/ajax/anotace.php",
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
...userAgentHeader,
|
"User-Agent":
|
||||||
|
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:139.0) Gecko/20100101 Firefox/139.0",
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
},
|
},
|
||||||
referrer: `https://amber.festivalfantazie.cz/program_linie.php?linie=${lineId}`,
|
referrer: `https://amber.festivalfantazie.cz/program_linie.php?linie=${lineId}`,
|
||||||
|
|
@ -181,25 +182,6 @@ export async function getScheduleForLine(lineId: number) {
|
||||||
const description$ = cheerio.load(descriptionHtml);
|
const description$ = cheerio.load(descriptionHtml);
|
||||||
const description = description$("description").text().trim();
|
const description = description$("description").text().trim();
|
||||||
|
|
||||||
const locationRes = await fetch(
|
|
||||||
`https://app.festivalfantazie.cz/program-detail/${eventIdNumber}`,
|
|
||||||
{
|
|
||||||
headers: userAgentHeader,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!locationRes.ok) {
|
|
||||||
throw new Error(
|
|
||||||
`Failed to fetch location for event ID ${eventIdNumber}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const locationHtml = await locationRes.text();
|
|
||||||
const location$ = cheerio.load(locationHtml);
|
|
||||||
const location = location$("div.row.mb-5 > div.col-6.mb-2:nth-of-type(2)")
|
|
||||||
.text()
|
|
||||||
.trim();
|
|
||||||
|
|
||||||
events.push({
|
events.push({
|
||||||
id: eventIdNumber,
|
id: eventIdNumber,
|
||||||
startTime,
|
startTime,
|
||||||
|
|
@ -209,7 +191,6 @@ export async function getScheduleForLine(lineId: number) {
|
||||||
description,
|
description,
|
||||||
type: $(td).find("td.program_typ").text().trim(),
|
type: $(td).find("td.program_typ").text().trim(),
|
||||||
lineId,
|
lineId,
|
||||||
location: location || undefined, // Optional location field
|
|
||||||
});
|
});
|
||||||
|
|
||||||
currentTime = new Date(endTime);
|
currentTime = new Date(endTime);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,10 @@ import type { Event } from "@/common/parser";
|
||||||
import { isEventFavorite } from "@/common/utils";
|
import { isEventFavorite } from "@/common/utils";
|
||||||
import { Button } from "./ui/button";
|
import { Button } from "./ui/button";
|
||||||
import { toggleFavoriteEvent } from "@/app/actions";
|
import { toggleFavoriteEvent } from "@/app/actions";
|
||||||
import { HeartMinusIcon, HeartPlusIcon } from "lucide-react";
|
import {
|
||||||
|
HeartMinusIcon,
|
||||||
|
HeartPlusIcon,
|
||||||
|
} from "lucide-react";
|
||||||
import { getLineById } from "@/db";
|
import { getLineById } from "@/db";
|
||||||
import { Badge } from "./ui/badge";
|
import { Badge } from "./ui/badge";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|
@ -21,15 +24,8 @@ export async function EventCard({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white dark:bg-gray-800 p-4 rounded-lg shadow-sm w-full">
|
<div className="bg-white dark:bg-gray-800 p-4 rounded-lg shadow-sm w-full">
|
||||||
<div className="flex items-start justify-between gap-2">
|
<div className="flex items-center justify-between gap-2">
|
||||||
<div>
|
|
||||||
<h3 className="text-lg font-semibold">{event.title}</h3>
|
<h3 className="text-lg font-semibold">{event.title}</h3>
|
||||||
{line && (
|
|
||||||
<Badge asChild variant="outline" className="my-2">
|
|
||||||
<Link href={`/line/${line.id}`}>{line.name}</Link>
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<form action={toggleFavoriteEvent}>
|
<form action={toggleFavoriteEvent}>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -38,21 +34,23 @@ export async function EventCard({
|
||||||
hidden
|
hidden
|
||||||
readOnly
|
readOnly
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button variant={isFavorite ? "default" : "secondary"} className="cursor-pointer">
|
||||||
variant={isFavorite ? "default" : "secondary"}
|
|
||||||
className="cursor-pointer"
|
|
||||||
>
|
|
||||||
{isFavorite ? <HeartMinusIcon /> : <HeartPlusIcon />}
|
{isFavorite ? <HeartMinusIcon /> : <HeartPlusIcon />}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
{line && (
|
||||||
|
<Badge asChild variant="outline" className='my-2'>
|
||||||
|
<Link href={`/line/${line.id}`}>{line.name}</Link>
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
<h6 className="text-xs text-gray-600 dark:text-gray-400">{event.name}</h6>
|
<h6 className="text-xs text-gray-600 dark:text-gray-400">{event.name}</h6>
|
||||||
<h5 className="text-md text-gray-500 dark:text-gray-300">
|
<h5 className="text-md text-gray-500 dark:text-gray-300">
|
||||||
{showDate
|
{showDate
|
||||||
? `${event.startTime.toLocaleDateString(["cs-CZ"], {
|
? `${event.startTime.toLocaleDateString(["cs-CZ"], {
|
||||||
month: "numeric",
|
month: "numeric",
|
||||||
day: "numeric",
|
day: "numeric",
|
||||||
weekday: "short",
|
weekday: 'short',
|
||||||
})} `
|
})} `
|
||||||
: ""}
|
: ""}
|
||||||
{event.startTime.toLocaleTimeString(["cs-CZ"], {
|
{event.startTime.toLocaleTimeString(["cs-CZ"], {
|
||||||
|
|
@ -67,11 +65,6 @@ export async function EventCard({
|
||||||
hour12: false,
|
hour12: false,
|
||||||
})}
|
})}
|
||||||
</h5>
|
</h5>
|
||||||
{event.location && (
|
|
||||||
<h6 className="text-xs text-gray-500 dark:text-gray-300">
|
|
||||||
{event.location}
|
|
||||||
</h6>
|
|
||||||
)}
|
|
||||||
<p className="text-sm text-gray-600 dark:text-gray-400">
|
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||||
{event.description}
|
{event.description}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import type { Event } from "@/common/parser";
|
import { Event } from "@/common/parser";
|
||||||
import { EventCard } from "./EventCard";
|
import { EventCard } from "./EventCard";
|
||||||
|
|
||||||
export function EventList({
|
export function EventList({
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ export const eventsTable = pgTable("eventsTable", {
|
||||||
title: text().notNull(),
|
title: text().notNull(),
|
||||||
description: text().notNull(),
|
description: text().notNull(),
|
||||||
type: text().notNull(),
|
type: text().notNull(),
|
||||||
location: text(), // Optional location field
|
|
||||||
lineId: integer()
|
lineId: integer()
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => linesTable.id, {
|
.references(() => linesTable.id, {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue