Section, dodanie sekcji z rozdzieleniem na standardowa i tą pod iframe

This commit is contained in:
dm
2025-11-21 07:17:05 +01:00
parent dafe9deaa6
commit f42a242d9c
17 changed files with 290 additions and 6 deletions

2
.gitignore vendored
View File

@@ -40,5 +40,5 @@ temp/
# Public generated
public/**/*.avif
public/**/*.webp
# public/**/*.webp
public/og/*.txt

View File

@@ -13,6 +13,7 @@
"@preact/signals": "^2.5.1",
"astro": "^5.16.0",
"js-yaml": "^4.1.0",
"marked": "^17.0.1",
"preact": "^10.27.2"
},
"devDependencies": {

BIN
public/images/fiber2.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

View File

@@ -0,0 +1,36 @@
---
import Markdown from "../../islands/Markdown.jsx";
const { section, index } = Astro.props;
const hasImage = !!section.image;
const reverse = index % 2 === 1;
---
<section class="fuz-section">
<div class={`fuz-section-grid ${hasImage ? "md:grid-cols-2" : "md:grid-cols-1"}`}>
{hasImage && (
<img
src={section.image}
alt={section.title}
class={`fuz-section-image ${reverse ? "md:order-1" : "md:order-2"}
${section.dimmed ? "fuz-image-dimmed" : ""}`}
/>
)}
<div class={`fuz-section-text ${hasImage ? (reverse ? "md:order-2" : "md:order-1") : ""}`}>
<h2 class="fuz-section-title text-center">{section.title}</h2>
<Markdown text={section.content} />
{section.button && (
<div class="mt-8 flex justify-center">
<a href={section.button.url} class="btn btn-outline">
{section.button.text}
</a>
</div>
)}
</div>
</div>
</section>

View File

@@ -0,0 +1,20 @@
---
import IframeChannelSwitcher from "../../islands/ChannelSwitcher.jsx";
const { section } = Astro.props;
---
<section class="fuz-section bg-transparent">
<div class="max-w-7xl mx-auto text-center">
{section.title && (
<h2 class="fuz-section-title">{section.title}</h2>
)}
{section.content && (
<div class="fuz-markdown mb-10" set:html={section.html} />
)}
<IframeChannelSwitcher client:load sets={section.iframe_sets} />
</div>
</section>

View File

@@ -0,0 +1,29 @@
---
import yaml from "js-yaml";
import fs from "fs";
import { marked } from "marked";
import SectionDefault from "./SectionDefault.astro";
import SectionIframeChannels from "./SectionIframeChannels.astro";
const { src } = Astro.props;
// Load YAML
const data = yaml.load(fs.readFileSync(src, "utf8")) ?? { sections: [] };
// Markdown → HTML
const sections = (data.sections as any[]).map((s: any) => ({
...s,
html: marked(s.content || "")
}));
---
{sections.map((section: any, index: number) => {
const type = section.type || "default";
if (type === "iframe-channels") {
return <SectionIframeChannels section={section} index={index} />;
}
return <SectionDefault section={section} index={index} />;
})}

View File

@@ -1,7 +1,8 @@
sections:
- title: "Internet Światłowodowy"
image: "/images/section-fiber.jpg"
image: "/images/section-fiber.webp"
dimmed: true
type: default
button:
text: "Zobacz ofertę →"
url: "/internet-swiatlowod/"
@@ -10,13 +11,36 @@ sections:
Odkryj komfort technologii stworzonej do pracy, rozrywki i życia bez ograniczeń.
- title: "Internet Radiowy"
image: "/images/section-radiowy.jpg"
- title: "Internet i Telewizja"
image: "/images/section-tv.webp"
dimmed: true
button:
text: "Zobacz ofertę →"
url: "/internet-telewizja/"
content: |
Internet + TV to połączenie stabilnego, szybkiego łącza z bogatą ofertą telewizyjną dla całej rodziny.
Korzystaj z internetu bez limitów i oglądaj swoje ulubione programy w perfekcyjnej jakości — w jednym prostym pakiecie.
- title: "Internet Radiowy"
image: "/images/section-radiowy.webp"
dimmed: true
type: default
button:
text: "Zobacz ofertę →"
url: "/internet-radiowy/"
content: |
Nowoczesna technologia radiowa gwarantuje stabilny internet o wysokiej wydajności tam, gdzie inne łącza nie mają szans.
To szybki start w świat cyfrowej pracy i rozrywki — bez konieczności instalacji kabli.
To szybki start w świat cyfrowej pracy i rozrywki — bez konieczności instalacji kabli.
- title: "Telefon"
image: "/images/section-phone.webp"
dimmed: true
button:
text: "Zobacz ofertę →"
url: "/internet-telewizja/"
content: |
Nasza telefonia wykorzystuje zaawansowaną technologię VoIP, dzięki której dźwięk jest wyraźny, a połączenia stabilne.
To idealne rozwiązanie dla domu i firm, które potrzebują jakości i przewidywalnych kosztów.

View File

@@ -0,0 +1,39 @@
import { useState } from "preact/hooks";
export default function ChannelSwitcher({ sets = [] }) {
const [activeId, setActiveId] = useState(sets[0]?.id);
const active = sets.find((x) => x.id === activeId);
const iframeSrc = `https://www.jambox.pl/iframe-pakiet-logo?p=${active?.p}`;
return (
<div class="w-full">
<div class="flex justify-center mb-10">
<div class="fuz-switch-group">
{sets.map((s) => (
<button
type="button"
class={`fuz-switch ${activeId === s.id ? "active" : ""}`}
onClick={() => setActiveId(s.id)}
>
{s.name}
</button>
))}
</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>
</div>
</div>
);
}

63
src/islands/Markdown.jsx Normal file
View File

@@ -0,0 +1,63 @@
import { marked } from "marked";
marked.setOptions({
gfm: true,
breaks: true,
headerIds: false,
mangle: false,
sanitize: false,
smartLists: true,
smartypants: false,
});
function applyShortcodes(md, ctx = {}) {
md = md.replace(/{{\s*channels\s*}}/g, () => {
if (!ctx.kanaly) return "";
const html = ctx.kanaly
.map(
(k) => `
<div class="flex items-center justify-center p-1">
<img
src="${k.logo}"
alt="${k.name}"
title="${k.name}"
class="channel-logo w-20 h-auto object-contain rounded"
/>
</div>
`
)
.join("");
return `
<div class="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-6 lg:grid-cols-10 gap-2 my-4">
${html}
</div>
`;
});
return md;
}
export default function FuzMarkdown({ text, ctx = {} }) {
if (!text) return null;
let processed = applyShortcodes(text, ctx);
// Konwersja kinków na modal linki
processed = processed.replace(
/\[([^\]]+)\]\(#([^)]+)\)/g,
`<a href="#" class="modal-link text-cyan-600 underline" data-modal="$2">$1</a>`
);
const html = marked(processed);
return (
<div
class="fuz-markdown max-w-none"
dangerouslySetInnerHTML={{ __html: html }}
/>
);
}

View File

@@ -1,6 +1,7 @@
---
import DefaultLayout from "../layouts/DefaultLayout.astro";
import Hero from "../components/hero/Hero.astro";
import SectionRenderer from "../components/sections/SectionRenderer.astro"
import yaml from "js-yaml";
import fs from "fs";
@@ -11,4 +12,5 @@ const hero = yaml.load(fs.readFileSync("./src/content/home/hero.yaml", "utf8"));
<DefaultLayout seo={seo}>
<Hero {...hero} />
<SectionRenderer src="./src/content/site/site.section.yaml" />
</DefaultLayout>

View File

@@ -2,4 +2,6 @@
@import "./theme.css";
@import "./navbar.css";
@import "./hero.css";
@import "./buttons.css";
@import "./buttons.css";
@import "./sections.css";
@import "./markdown.css";

45
src/styles/markdown.css Normal file
View File

@@ -0,0 +1,45 @@
.fuz-markdown {
@apply leading-relaxed text-base md:text-lg;
/* odstępy między elementami */
}
.fuz-markdown p {
@apply mb-4 text-3xl;
}
.fuz-markdown h1 {
@apply text-3xl font-bold mt-8 mb-4;
}
.fuz-markdown h2 {
@apply text-2xl font-semibold mt-6 mb-3;
}
.fuz-markdown h3 {
@apply text-xl font-semibold mt-4 mb-2;
}
.fuz-markdown ul {
@apply list-disc pl-6 mb-4;
}
.fuz-markdown ol {
@apply list-decimal pl-6 mb-4;
}
.fuz-markdown li {
@apply mb-1;
}
.fuz-markdown a {
@apply text-blue-600 dark:text-blue-400 underline hover:no-underline;
}
.fuz-markdown blockquote {
@apply border-l-4 border-gray-300 dark:border-gray-700 pl-4 italic mb-4;
}
.fuz-markdown strong {
@apply font-semibold;
}

23
src/styles/sections.css Normal file
View File

@@ -0,0 +1,23 @@
.fuz-section {
@apply py-20 px-6;
}
.fuz-section-grid {
@apply grid items-center gap-10 max-w-7xl mx-auto;
}
.fuz-section-image {
@apply w-full h-full object-cover ;
}
.fuz-image-dimmed {
opacity: 0.75;
}
.fuz-section-title {
@apply text-5xl md:text-5xl font-bold mb-6;
}
.fuz-section-text {
@apply max-w-4xl mx-auto;
}