diff --git a/package.json b/package.json index f32f2a3..1e78aff 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,10 @@ "scripts": { "dev": "astro dev", "build": "astro build", - "preview": "astro preview" + "preview": "astro preview", + "clean": "rimraf node_modules .astro .vite dist .cache .turbo package-lock.json", + "fresh": "npm run clean && npm install", + "dev:clean": "npm run clean && npm install && astro dev" }, "dependencies": { "@astrojs/node": "^9.5.1", @@ -26,6 +29,7 @@ "@types/better-sqlite3": "^7.6.13", "autoprefixer": "^10.4.0", "postcss": "^8.4.0", + "rimraf": "^6.1.2", "tailwindcss": "^3.4.0" } } diff --git a/public/logo.webp b/public/logo.webp index 8d22fcd..ac3eb21 100644 Binary files a/public/logo.webp and b/public/logo.webp differ diff --git a/public/logon.webp b/public/logon.webp new file mode 100644 index 0000000..8d22fcd Binary files /dev/null and b/public/logon.webp differ diff --git a/src/assets/logo.webp b/src/assets/logo.webp index 913e7ee..ac3eb21 100644 Binary files a/src/assets/logo.webp and b/src/assets/logo.webp differ diff --git a/public/logo.webp1 b/src/assets/logon.webp similarity index 100% rename from public/logo.webp1 rename to src/assets/logon.webp diff --git a/src/content/home/hero.yaml b/src/content/home/hero.yaml index e2dfee2..a0f1bde 100644 --- a/src/content/home/hero.yaml +++ b/src/content/home/hero.yaml @@ -1,20 +1,20 @@ title: - - "Internet i Telewizja FUZ" + - Internet i Telewizja FUZ subtitle: - - Doskanały internet światłowodowy i telewizja w Wyszkowie i okolicach, - - "Lokalny operator, znamy Twoją okolicę," - - "Realny serwis, szybkie wsparcie," - - "Stabilna infrastruktura światłowodowa," + - Doskonały internet światłowodowy i telewizja w Wyszkowie i okolicach, + - Lokalny operator, znamy Twoją okolicę, + - Realny serwis, szybkie wsparcie, + - Stabilna infrastruktura światłowodowa, description: | -imageUrl: "home.webp" +imageUrl: home.webp ctas: - - label: "Zobacz ofertę Internetu" - href: "/internet-swiatlowodowy" - title: "Przejdź do oferty Internetu światłowodowego" + - label: Zobacz ofertę Internetu + href: /internet-swiatlowodowy + title: Przejdź do oferty Internetu światłowodowego primary: false - - label: "Zobacz ofertę Telewizji" - href: "/internet-telewizja" - title: "Przejdź do oferty Internet + Telewizja w FUZ" + - label: Zobacz ofertę Telewizji + href: /internet-telewizja + title: Przejdź do oferty Internet + Telewizja w FUZ primary: false diff --git a/src/data/ServicesRange.db b/src/data/ServicesRange.db index d8a9b8e..9d28ece 100644 Binary files a/src/data/ServicesRange.db and b/src/data/ServicesRange.db differ diff --git a/src/data/ServicesRange.db-shm b/src/data/ServicesRange.db-shm index 0bf83d6..fe9ac28 100644 Binary files a/src/data/ServicesRange.db-shm and b/src/data/ServicesRange.db-shm differ diff --git a/src/data/ServicesRange.db-wal b/src/data/ServicesRange.db-wal index b851cab..e69de29 100644 Binary files a/src/data/ServicesRange.db-wal and b/src/data/ServicesRange.db-wal differ diff --git a/src/islands/jambox/JamboxChannelsSearch.jsx b/src/islands/jambox/JamboxChannelsSearch.jsx index a32ee1b..c976d7a 100644 --- a/src/islands/jambox/JamboxChannelsSearch.jsx +++ b/src/islands/jambox/JamboxChannelsSearch.jsx @@ -126,17 +126,34 @@ export default function JamboxChannelsSearch() { setWanted([]); } - // ========================================= - // ✅ sugestie pakietów dla koszyka - // - GŁÓWNE: exact/ranked (z count) - // - TEMATYCZNE: dodatki do dokupienia (bez liczenia) - // ========================================= const packageSuggestions = useMemo(() => { - if (!wanted.length) return { exact: [], ranked: [], thematic: [] }; + if (!wanted.length) return { exact: [], ranked: [], thematic: [], baseWantedLen: 0, wantedLen: 0 }; + + // ✅ kanały, które mają pakiety główne (tylko te liczymy w dopasowaniu "głównych") + const baseWanted = wanted.filter((ch) => Array.isArray(ch.packages) && ch.packages.length > 0); + const baseWantedLen = baseWanted.length; // ======= GŁÓWNE ======= + // jeśli nie ma żadnego kanału "bazowego", nie ma co liczyć dopasowania bazowych + if (baseWantedLen === 0) { + // nadal zwracamy tematyczne + const thematicMap = new Map(); + for (const ch of wanted) { + const tp = Array.isArray(ch.thematic_packages) ? ch.thematic_packages : []; + for (const p of tp) { + const tid = String(p?.tid ?? "").trim(); + const name = String(p?.name ?? "").trim(); + if (!tid || !name) continue; + if (!thematicMap.has(tid)) thematicMap.set(tid, { tid, name }); + } + } + const thematic = Array.from(thematicMap.values()).sort((a, b) => a.name.localeCompare(b.name, "pl")); + + return { exact: [], ranked: [], thematic, baseWantedLen, wantedLen: wanted.length }; + } + const counts = new Map(); // key = packageName - for (const ch of wanted) { + for (const ch of baseWanted) { const pkgs = Array.isArray(ch.packages) ? ch.packages : []; for (const p of pkgs) { const name = String(p?.name ?? "").trim(); @@ -150,20 +167,18 @@ export default function JamboxChannelsSearch() { const all = Array.from(counts.values()); const exact = all - .filter((p) => p.count === wanted.length) + .filter((p) => p.count === baseWantedLen) .sort((a, b) => a.name.localeCompare(b.name, "pl")); const ranked = all - .filter((p) => p.count < wanted.length) + .filter((p) => p.count < baseWantedLen) .sort((a, b) => b.count - a.count || a.name.localeCompare(b.name, "pl")) .slice(0, 12); // ======= TEMATYCZNE (dodatki) ======= const thematicMap = new Map(); // key = tid for (const ch of wanted) { - const tp = Array.isArray(ch.thematic_packages) - ? ch.thematic_packages - : []; + const tp = Array.isArray(ch.thematic_packages) ? ch.thematic_packages : []; for (const p of tp) { const tid = String(p?.tid ?? "").trim(); const name = String(p?.name ?? "").trim(); @@ -176,9 +191,10 @@ export default function JamboxChannelsSearch() { a.name.localeCompare(b.name, "pl") ); - return { exact, ranked, thematic }; + return { exact, ranked, thematic, baseWantedLen, wantedLen: wanted.length }; }, [wanted]); + return (

Wyszukiwanie kanałów w pakietach telewizji

@@ -260,7 +276,7 @@ export default function JamboxChannelsSearch() { onClick={() => scrollToPackage(p.name)} title={`Zawiera ${p.count}/${wanted.length} wybranych kanałów`} > - {p.name} ({p.count}/{wanted.length}) + {p.name} ({p.count}/{packageSuggestions.baseWantedLen}) ))}
diff --git a/src/layouts/BaseHead.astro b/src/layouts/BaseHead.astro index 1e2f1b9..ef4b1fc 100644 --- a/src/layouts/BaseHead.astro +++ b/src/layouts/BaseHead.astro @@ -4,54 +4,80 @@ import fs from "fs"; const seo = Astro.props.seo ?? {}; const globalSeo = yaml.load( - fs.readFileSync("./src/content/home/seo.yaml", "utf8") + fs.readFileSync("./src/content/home/seo.yaml", "utf8"), ); const { site, company } = globalSeo; - const page = seo.page ?? {}; +// ===== helpers ===== +function stripTrailingSlash(s = "") { + return String(s).replace(/\/$/, ""); +} +function stripLeadingSlash(s = "") { + return String(s).replace(/^\//, ""); +} +function isAbsoluteUrl(s = "") { + return /^https?:\/\//i.test(String(s)); +} +function joinUrl(base = "", path = "") { + const b = stripTrailingSlash(base); + const p = String(path || ""); + if (!p) return b; + if (isAbsoluteUrl(p)) return p; + return `${b}/${stripLeadingSlash(p)}`; +} + +// ===== origin / base for meta ===== +// Astro.url.origin daje aktualny host (test/prod) – dokładnie to chcemy do OG/WhatsApp +const origin = Astro.url?.origin || site.url; +const baseUrl = stripTrailingSlash(origin); + +// ===== page fields ===== const title = page.title ?? site.name; const description = page.description ?? site.description; -const image = page.image ?? site.logo; -const canonical = site.url + (page.url ?? "/"); + +const rawImage = page.image ?? site.logo; +const image = joinUrl(baseUrl, rawImage); + +const canonical = joinUrl(baseUrl, page.url ?? "/"); const keywords = page.keywords ?? []; const extraSchema = page.schema ?? null; -// JSON-LD objects +// JSON-LD objects (tu też używamy baseUrl, żeby nie rozjeżdżało się między test/prod) const schemaWebsite = { "@context": "https://schema.org", "@type": "WebSite", - "url": site.url, - "name": site.name, - "potentialAction": { + url: baseUrl, + name: site.name, + potentialAction: { "@type": "SearchAction", - "target": `${site.url}/wyszukiwarka?query={search_term_string}`, - "query-input": "required name=search_term_string" - } + target: `${baseUrl}/wyszukiwarka?query={search_term_string}`, + "query-input": "required name=search_term_string", + }, }; const schemaLocalBusiness = { "@context": "https://schema.org", "@type": "LocalBusiness", - "name": company.name, - "image": site.url + company.logo, - "telephone": company.phone, - "email": company.email, - "address": { + name: company.name, + image: joinUrl(baseUrl, company.logo), + telephone: company.phone, + email: company.email, + address: { "@type": "PostalAddress", - "streetAddress": company.street, - "addressLocality": company.city, - "postalCode": company.postal, - "addressCountry": company.country + streetAddress: company.street, + addressLocality: company.city, + postalCode: company.postal, + addressCountry: company.country, }, - "geo": { + geo: { "@type": "GeoCoordinates", - "latitude": company.lat, - "longitude": company.lon + latitude: company.lat, + longitude: company.lon, }, - "url": site.url + url: baseUrl, }; // JSON strings @@ -67,9 +93,7 @@ const jsonExtra = extraSchema ? JSON.stringify(extraSchema) : null; {title} - {keywords.length > 0 && ( - - )} + {keywords.length > 0 && } @@ -79,7 +103,12 @@ const jsonExtra = extraSchema ? JSON.stringify(extraSchema) : null; + + + + + @@ -94,9 +123,7 @@ const jsonExtra = extraSchema ? JSON.stringify(extraSchema) : null; - {jsonExtra && ( - - )} + {jsonExtra && }