feat: use real blog cover images

Replace the SVG placeholder illustrations with blog1/blog2 covers and
remove the unused illustrations component.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
vargha1
2026-10-03 15:10:56 +03:30
parent b9cc3c6349
commit 6b2c5ec62d
5 changed files with 22 additions and 68 deletions

BIN
public/blog1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
public/blog2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@@ -3,7 +3,7 @@
import Link from "next/link"; import Link from "next/link";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import { Select } from "@/components/ui/select"; import { Select } from "@/components/ui/select";
import { Telescope, Target } from "@/components/ui/illustrations"; import Image from "next/image";
import { Reveal } from "@/components/ui/reveal"; import { Reveal } from "@/components/ui/reveal";
import { categories, posts, type Post } from "@/data/posts"; import { categories, posts, type Post } from "@/data/posts";
@@ -25,10 +25,11 @@ function boundary({ y, m, d }: DateParts, end: boolean) {
const dateFormat = new Intl.DateTimeFormat("en-US", { month: "short", day: "numeric", year: "numeric", timeZone: "UTC" }); const dateFormat = new Intl.DateTimeFormat("en-US", { month: "short", day: "numeric", year: "numeric", timeZone: "UTC" });
const themes = { // The orange cover is the blue telescope image hue-shifted.
navy: "bg-[#11192d]", const covers = {
blue: "bg-linear-to-br from-[#0160d4] to-[#0a8bff]", dart: { src: "/blog1.png", className: "" },
orange: "bg-linear-to-br from-[#f3610c] to-[#ffb020]", telescope: { src: "/blog2.png", className: "" },
"telescope-orange": { src: "/blog2.png", className: "hue-rotate-[188deg] saturate-125" },
}; };
function CalendarIcon() { function CalendarIcon() {
@@ -41,12 +42,11 @@ function CalendarIcon() {
} }
function PostCard({ post }: { post: Post }) { function PostCard({ post }: { post: Post }) {
const Art = post.art === "telescope" ? Telescope : Target; const cover = covers[post.cover];
return ( return (
<article className="flex flex-col gap-3"> <article className="flex flex-col gap-3">
<div className={`relative aspect-[16/9] overflow-hidden rounded-2xl ${themes[post.theme]}`}> <div className="relative aspect-[361/208] overflow-hidden rounded-2xl">
<div aria-hidden className="absolute -right-10 top-6 size-56 rounded-full border-20 border-white/10" /> <Image src={cover.src} alt="" fill sizes="(min-width: 640px) 25rem, 100vw" className={`object-cover ${cover.className}`} />
<Art className="absolute -left-6 top-0 h-[115%] w-auto drop-shadow-xl" />
</div> </div>
<div className="flex flex-col gap-1 px-2"> <div className="flex flex-col gap-1 px-2">
<h3 className="text-sm font-bold text-[#11192d]">{post.title}</h3> <h3 className="text-sm font-bold text-[#11192d]">{post.title}</h3>

View File

@@ -1,45 +0,0 @@
/** Placeholder 3D-style illustrations. Swap for the real artwork when available. */
function Defs() {
return (
<defs>
<linearGradient id="ill-body" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stopColor="#ffffff" />
<stop offset="1" stopColor="#c9d0dd" />
</linearGradient>
</defs>
);
}
export function Telescope({ className = "" }: { className?: string }) {
return (
<svg viewBox="0 0 200 200" aria-hidden className={className}>
<Defs />
<ellipse cx="100" cy="182" rx="38" ry="7" fill="#000" opacity="0.12" />
<path d="M90 112 70 178h60l-20-62Z" fill="url(#ill-body)" />
<circle cx="100" cy="112" r="9" fill="#e6e9ef" />
<g transform="rotate(-35 100 100)">
<rect x="44" y="82" width="96" height="38" rx="16" fill="url(#ill-body)" />
<rect x="126" y="76" width="22" height="50" rx="9" fill="#f4f6fa" />
<ellipse cx="146" cy="101" rx="8" ry="19" fill="#aeb6c6" />
<rect x="60" y="68" width="40" height="12" rx="6" fill="url(#ill-body)" />
</g>
</svg>
);
}
export function Target({ className = "" }: { className?: string }) {
return (
<svg viewBox="0 0 200 200" aria-hidden className={className}>
<Defs />
<ellipse cx="100" cy="176" rx="52" ry="8" fill="#000" opacity="0.12" />
<circle cx="96" cy="108" r="62" fill="url(#ill-body)" />
<circle cx="96" cy="108" r="46" fill="#dfe3ec" />
<circle cx="96" cy="108" r="31" fill="url(#ill-body)" />
<circle cx="96" cy="108" r="15" fill="#c2cadb" />
<path d="M96 108 168 38" stroke="#d5dbe7" strokeWidth="6" strokeLinecap="round" />
<path d="m150 38 22-6-6 22-10-4-6-12Z" fill="url(#ill-body)" />
<path d="m132 54 12 4-18 18-6-10 12-12Z" fill="#f4f6fa" />
</svg>
);
}

View File

@@ -5,23 +5,22 @@ export type Post = {
category: string; category: string;
/** ISO date (YYYY-MM-DD) */ /** ISO date (YYYY-MM-DD) */
date: string; date: string;
theme: "navy" | "blue" | "orange"; cover: "dart" | "telescope" | "telescope-orange";
art: "telescope" | "target";
}; };
export const categories = ["Industry Insights", "Guides", "Product Updates", "Customer Stories"]; export const categories = ["Industry Insights", "Guides", "Product Updates", "Customer Stories"];
export const posts: Post[] = [ export const posts: Post[] = [
{ slug: "choosing-tour-booking-software", title: "How to choose the right tour booking software", excerpt: "A practical checklist for comparing booking platforms for tours, transfers and rentals.", category: "Guides", date: "2026-09-30", theme: "navy", art: "target" }, { slug: "choosing-tour-booking-software", title: "How to choose the right tour booking software", excerpt: "A practical checklist for comparing booking platforms for tours, transfers and rentals.", category: "Guides", date: "2026-09-30", cover: "dart" },
{ slug: "ai-in-tour-operations", title: "How AI is changing tour operations", excerpt: "From dynamic pricing to automated customer replies, where AI already saves operators time.", category: "Industry Insights", date: "2026-09-27", theme: "blue", art: "telescope" }, { slug: "ai-in-tour-operations", title: "How AI is changing tour operations", excerpt: "From dynamic pricing to automated customer replies, where AI already saves operators time.", category: "Industry Insights", date: "2026-09-27", cover: "telescope" },
{ slug: "ota-connectivity-explained", title: "OTA connectivity explained", excerpt: "How to distribute inventory to marketplaces without double bookings or manual updates.", category: "Guides", date: "2026-09-21", theme: "orange", art: "telescope" }, { slug: "ota-connectivity-explained", title: "OTA connectivity explained", excerpt: "How to distribute inventory to marketplaces without double bookings or manual updates.", category: "Guides", date: "2026-09-21", cover: "telescope-orange" },
{ slug: "voyager-fleet-management", title: "New: fleet and staff scheduling", excerpt: "Assign vehicles and drivers to departures in a few clicks, with conflicts flagged for you.", category: "Product Updates", date: "2026-09-14", theme: "navy", art: "target" }, { slug: "voyager-fleet-management", title: "New: fleet and staff scheduling", excerpt: "Assign vehicles and drivers to departures in a few clicks, with conflicts flagged for you.", category: "Product Updates", date: "2026-09-14", cover: "dart" },
{ slug: "direct-bookings-playbook", title: "A playbook for more direct bookings", excerpt: "Lower your OTA commissions by turning your own website into your best sales channel.", category: "Industry Insights", date: "2026-08-29", theme: "navy", art: "target" }, { slug: "direct-bookings-playbook", title: "A playbook for more direct bookings", excerpt: "Lower your OTA commissions by turning your own website into your best sales channel.", category: "Industry Insights", date: "2026-08-29", cover: "dart" },
{ slug: "city-tours-case-study", title: "How a city tour operator doubled online sales", excerpt: "A look at the workflows and tools behind a year of steady growth.", category: "Customer Stories", date: "2026-08-17", theme: "blue", art: "telescope" }, { slug: "city-tours-case-study", title: "How a city tour operator doubled online sales", excerpt: "A look at the workflows and tools behind a year of steady growth.", category: "Customer Stories", date: "2026-08-17", cover: "telescope" },
{ slug: "pricing-your-tours", title: "Fixed vs. dynamic pricing for tours", excerpt: "When to keep prices simple and when demand-based pricing pays off.", category: "Guides", date: "2026-07-22", theme: "orange", art: "telescope" }, { slug: "pricing-your-tours", title: "Fixed vs. dynamic pricing for tours", excerpt: "When to keep prices simple and when demand-based pricing pays off.", category: "Guides", date: "2026-07-22", cover: "telescope-orange" },
{ slug: "payments-update", title: "Faster payouts and simpler reconciliation", excerpt: "What changed in payments, and how it affects your month-end reporting.", category: "Product Updates", date: "2026-07-03", theme: "navy", art: "target" }, { slug: "payments-update", title: "Faster payouts and simpler reconciliation", excerpt: "What changed in payments, and how it affects your month-end reporting.", category: "Product Updates", date: "2026-07-03", cover: "dart" },
{ slug: "rental-business-growth", title: "Adding rentals to a tour business", excerpt: "Why many operators expand into vehicle and equipment rentals, and how to start.", category: "Industry Insights", date: "2026-06-12", theme: "navy", art: "target" }, { slug: "rental-business-growth", title: "Adding rentals to a tour business", excerpt: "Why many operators expand into vehicle and equipment rentals, and how to start.", category: "Industry Insights", date: "2026-06-12", cover: "dart" },
{ slug: "transfer-company-story", title: "A transfer company goes paperless", excerpt: "Replacing spreadsheets and phone calls with one connected booking system.", category: "Customer Stories", date: "2026-05-20", theme: "blue", art: "telescope" }, { slug: "transfer-company-story", title: "A transfer company goes paperless", excerpt: "Replacing spreadsheets and phone calls with one connected booking system.", category: "Customer Stories", date: "2026-05-20", cover: "telescope" },
{ slug: "crm-for-operators", title: "Why tour operators need a CRM", excerpt: "Keep every guest, enquiry and repeat booking in one place.", category: "Guides", date: "2026-04-08", theme: "orange", art: "telescope" }, { slug: "crm-for-operators", title: "Why tour operators need a CRM", excerpt: "Keep every guest, enquiry and repeat booking in one place.", category: "Guides", date: "2026-04-08", cover: "telescope-orange" },
{ slug: "api-and-integrations", title: "API and integrations: what is new", excerpt: "New endpoints and partner integrations for connecting Voyager to your stack.", category: "Product Updates", date: "2026-03-15", theme: "navy", art: "target" }, { slug: "api-and-integrations", title: "API and integrations: what is new", excerpt: "New endpoints and partner integrations for connecting Voyager to your stack.", category: "Product Updates", date: "2026-03-15", cover: "dart" },
]; ];