Zmiana iframe listy kanałow na pobierane lokalnie i parsowane
This commit is contained in:
@@ -1,20 +1,26 @@
|
||||
---
|
||||
import ChannelSwitcher from "../../islands/ChannelSwitcher.jsx";
|
||||
|
||||
const { section } = Astro.props;
|
||||
---
|
||||
<section class="fuz-section bg-transparent">
|
||||
|
||||
<section class="f-section">
|
||||
<div class="max-w-7xl mx-auto text-center">
|
||||
|
||||
{section.title && (
|
||||
<h2 class="fuz-section-title">{section.title}</h2>
|
||||
<h2 class="f-section-title">{section.title}</h2>
|
||||
)}
|
||||
|
||||
{section.content && (
|
||||
<div class="fuz-markdown mb-10" set:html={section.html} />
|
||||
<div class="f-markdown mb-10" set:html={section.html} />
|
||||
)}
|
||||
|
||||
<ChannelSwitcher client:load sets={section.iframe_sets} title={section.title} />
|
||||
{section.iframe_sets && section.iframe_sets.length > 0 && (
|
||||
<ChannelSwitcher
|
||||
client:load
|
||||
sets={section.iframe_sets}
|
||||
title={section.title}
|
||||
/>
|
||||
)}
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -1,19 +1,32 @@
|
||||
import { useState } from "preact/hooks";
|
||||
import { useState, useEffect } from "preact/hooks";
|
||||
|
||||
export default function ChannelSwitcher({ sets = [], title = "" }) {
|
||||
const [activeId, setActiveId] = useState(sets[0]?.id);
|
||||
const [channels, setChannels] = useState([]);
|
||||
|
||||
const active = sets.find((x) => x.id === activeId);
|
||||
const iframeSrc = `https://www.jambox.pl/iframe-pakiet-logo?p=${active?.p}`;
|
||||
|
||||
useEffect(() => {
|
||||
if (!active) return;
|
||||
|
||||
fetch(`/api/jambox/${active.p}`)
|
||||
.then((r) => r.json())
|
||||
.then((data) => {
|
||||
setChannels(data);
|
||||
})
|
||||
.catch(() => setChannels([]));
|
||||
}, [active]);
|
||||
|
||||
return (
|
||||
<div class="w-full">
|
||||
|
||||
{/* SWITCHER */}
|
||||
<div class="flex justify-center mb-10">
|
||||
<div class="fuz-switch-group">
|
||||
<div class="f-switch-group">
|
||||
{sets.map((s) => (
|
||||
<button
|
||||
type="button"
|
||||
class={`fuz-switch ${activeId === s.id ? "active" : ""}`}
|
||||
class={`f-switch ${activeId === s.id ? "active" : ""}`}
|
||||
onClick={() => setActiveId(s.id)}
|
||||
title={title}
|
||||
>
|
||||
@@ -23,16 +36,31 @@ export default function ChannelSwitcher({ sets = [], title = "" }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 🔹 Iframe */}
|
||||
<div class="w-full">
|
||||
<div class="fuz-iframe-wrapper">
|
||||
<iframe
|
||||
title="Lista kanałów"
|
||||
src={iframeSrc}
|
||||
class="fuz-iframe"
|
||||
loading="lazy"
|
||||
></iframe>
|
||||
</div>
|
||||
{/* LISTA KANAŁÓW */}
|
||||
<div class="f-section-channel">
|
||||
|
||||
{channels.length === 0 && (
|
||||
<p class="text-center col-span-full py-1">
|
||||
Ładowanie…
|
||||
</p>
|
||||
)}
|
||||
|
||||
{channels.map((ch) => (
|
||||
<div
|
||||
class="f-channel-box"
|
||||
>
|
||||
<img
|
||||
src={ch.logo}
|
||||
alt={ch.title}
|
||||
class="h-14 object-contain "
|
||||
loading="lazy"
|
||||
/>
|
||||
<p class="text-center text-sm text-[var(--fuz-text)] mt-2">
|
||||
{ch.title}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
42
src/pages/api/jambox/[id].ts
Normal file
42
src/pages/api/jambox/[id].ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import type { APIRoute } from "astro";
|
||||
import { JSDOM } from "jsdom";
|
||||
|
||||
interface Channel {
|
||||
title: string;
|
||||
logo: string;
|
||||
}
|
||||
|
||||
const cache = new Map<string, { time: number; data: Channel[] }>();
|
||||
const CACHE_TIME = 1000 * 60 * 60 * 24 * 30; //miesiąc
|
||||
|
||||
export const GET: APIRoute = async ({ params }) => {
|
||||
const id = params.id!;
|
||||
const cached = cache.get(id);
|
||||
|
||||
if (cached && Date.now() - cached.time < CACHE_TIME) {
|
||||
return new Response(JSON.stringify(cached.data), {
|
||||
headers: { "Content-Type": "application/json" }
|
||||
});
|
||||
}
|
||||
|
||||
const url = `https://www.jambox.pl/iframe-pakiet-logo?p=${id}`;
|
||||
const resp = await fetch(url, { headers: { "User-Agent": "Mozilla/5.0" } });
|
||||
|
||||
const html = await resp.text();
|
||||
const dom = new JSDOM(html);
|
||||
|
||||
const images = [
|
||||
...dom.window.document.querySelectorAll("img.imagefield-field_logo")
|
||||
];
|
||||
|
||||
const channels = images.map((img) => ({
|
||||
title: img.getAttribute("alt")?.trim() ?? "",
|
||||
logo: img.getAttribute("src") ?? "",
|
||||
}));
|
||||
|
||||
cache.set(id, { time: Date.now(), data: channels });
|
||||
|
||||
return new Response(JSON.stringify(channels), {
|
||||
headers: { "Content-Type": "application/json" }
|
||||
});
|
||||
};
|
||||
@@ -1,48 +1,36 @@
|
||||
@layer components {
|
||||
#cookie-banner {
|
||||
@apply fixed bottom-0 left-0 w-full translate-y-full transition-transform duration-500 ease-in-out;
|
||||
background: var(--f-background-invert);
|
||||
color: var(--f-text-invert);
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||||
background: var(--f-cookie-background);
|
||||
color: var(--f-cookie-text);
|
||||
/* border-top: 1px solid rgba(0, 0, 0, 0.1); */
|
||||
}
|
||||
|
||||
.f-cookie-panel-inner {
|
||||
@apply max-w-4xl mx-auto flex flex-col md:flex-row items-start
|
||||
md:items-center justify-between gap-4 px-6 py-6;
|
||||
@apply max-w-5xl mx-auto flex flex-col md:flex-row items-start md:items-center justify-between gap-4 px-6 py-6;
|
||||
}
|
||||
|
||||
.f-cookie-text{
|
||||
.f-cookie-text {
|
||||
@apply text-base leading-snug;
|
||||
}
|
||||
|
||||
.f-cookie-privacy-link {
|
||||
@apply ml-3;
|
||||
color: var(--btn-outline-invert);
|
||||
color: var(--f-link-text);
|
||||
}
|
||||
|
||||
.f-cookie-accept,
|
||||
.f-cookie-reject {
|
||||
@apply px-4 py-2 rounded-md text-sm font-medium transition-colors;
|
||||
@apply px-8 py-4 rounded-md text-sm font-medium transition-colors;
|
||||
}
|
||||
|
||||
.f-cookie-accept {
|
||||
background: var(--btn-bg-invert);
|
||||
color: var(--btn-text-invert);
|
||||
}
|
||||
|
||||
.f-cookie-accept:hover {
|
||||
background: var(--fuz-accent-hover);
|
||||
.f-cookie-accept {
|
||||
background: var(--f-cookie-accept-background);
|
||||
color: var(--f-cookie-accept-text);
|
||||
}
|
||||
|
||||
.f-cookie-reject {
|
||||
@apply border;
|
||||
border-color: var(--btn-outline-invert);
|
||||
color: var(--btn-outline-invert);
|
||||
background: transparent;
|
||||
background: var(--f-cookie-reject-background);
|
||||
color: var(--f-cookie-reject-text);
|
||||
}
|
||||
|
||||
.f-cookie-reject:hover {
|
||||
background: var(--btn-outline-bg-invert);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
.f-switches-wrapper {
|
||||
@apply flex flex-wrap justify-center gap-6 mb-12;
|
||||
@apply flex flex-wrap justify-center gap-6 mb-10;
|
||||
}
|
||||
|
||||
.f-switch-group {
|
||||
@apply inline-flex overflow-hidden relative bg-[var(--f-background-switch)];
|
||||
@apply inline-flex overflow-hidden relative bg-[var(--f-background-switch)] mt-8;
|
||||
}
|
||||
|
||||
.f-switch {
|
||||
|
||||
@@ -43,7 +43,15 @@
|
||||
}
|
||||
|
||||
|
||||
.fuz-iframe-box {
|
||||
.f-section-channel {
|
||||
@apply grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-8 gap-2;
|
||||
}
|
||||
|
||||
.f-channel-box {
|
||||
@apply flex flex-col items-center p-4 rounded-xl bg-[var(--f-background)] border border-[var(--f-offers-border)] shadow-sm hover:shadow-md transition
|
||||
}
|
||||
|
||||
/* .fuz-iframe-box {
|
||||
@apply bg-white dark:bg-slate-800 p-4 rounded-xl border border-gray-200 dark:border-slate-700 shadow;
|
||||
}
|
||||
|
||||
@@ -64,4 +72,4 @@
|
||||
|
||||
.dark .fuz-iframe {
|
||||
background: transparent !important;
|
||||
}
|
||||
} */
|
||||
@@ -69,27 +69,12 @@
|
||||
--f-offers-popular: var(--brand-light);
|
||||
--f-offers-popular-bg: color-mix(in srgb, var(--f-offers-popular) 22%, transparent);
|
||||
|
||||
/* Invert Color */
|
||||
/* --f-background-invert: #0d1117;
|
||||
--f-text-invert: #e6edf3;
|
||||
--btn-bg-invert: #58a6ff;
|
||||
--btn-text-invert: #0d1117;
|
||||
--btn-outline-invert: #58a6ff;
|
||||
--btn-outline-bg-invert: rgba(88, 166, 255, 0.15); */
|
||||
/* Links */
|
||||
/* --fuz-link: #0050c8;
|
||||
--fuz-link-hover: #003f9a; */
|
||||
--f-cookie-background: var(--text1-light);
|
||||
--f-cookie-text: var(--surface2-light);
|
||||
|
||||
/* Accent (buttons, highlights) */
|
||||
/* --fuz-accent: #0066ff;
|
||||
--fuz-accent-hover: #004bcc;
|
||||
--fuz-accent-text: #ffffff;
|
||||
|
||||
|
||||
--btn-ghost-text: var(--f-text);
|
||||
--btn-ghost-hover-bg: rgba(0, 0, 0, 0.05);
|
||||
---f-border-color: rgb(209 213 219); */
|
||||
/* / var(--tw-border-opacity, 1)); */
|
||||
--f-cookie-accept-background: green;
|
||||
/* --f-cookie-accept-text: */
|
||||
--f-cookie-reject-background: var(--text2-light);
|
||||
}
|
||||
|
||||
:root.dark {
|
||||
@@ -128,36 +113,12 @@
|
||||
--f-offers-popular: var(--brand-dark);
|
||||
--f-offers-popular-bg: color-mix(in srgb, var(--f-offers-popular) 22%, transparent);
|
||||
|
||||
--f-cookie-background: var(--text1-light);
|
||||
--f-cookie-text: var(--surface2-light);
|
||||
|
||||
|
||||
/* Invert Color */
|
||||
--f-background-invert: #ffffff;
|
||||
--f-text-invert: #0d0d0d;
|
||||
--btn-bg-invert: #0066ff;
|
||||
--btn-text-invert: #ffffff;
|
||||
--btn-outline-invert: #0066ff;
|
||||
|
||||
/* Links (GitHub Dark palette) */
|
||||
--fuz-link: var(--brand-dim);
|
||||
--fuz-link-hover: #79b7ff;
|
||||
|
||||
|
||||
|
||||
/* Accent */
|
||||
--fuz-accent: hsl(var(--hue) calc(var(--saturation) / 1.25) calc(var(--lightness) / 1.25));
|
||||
--fuz-accent-hover: #79b7ff;
|
||||
--fuz-accent-text: #0d1117;
|
||||
|
||||
/* Buttons */
|
||||
|
||||
|
||||
|
||||
|
||||
--btn-ghost-text: var(--f-text);
|
||||
--btn-ghost-hover-bg: rgba(255, 255, 255, 0.08);
|
||||
|
||||
--f-border-color: rgb(209 213 219);
|
||||
/* / var(--tw-border-opacity, 1)) */
|
||||
--f-cookie-accept-background: green;
|
||||
/* --f-cookie-accept-text: */
|
||||
--f-cookie-reject-background: var(--text2-light);
|
||||
}
|
||||
|
||||
/* Body */
|
||||
|
||||
Reference in New Issue
Block a user