Plot = import("https://cdn.jsdelivr.net/npm/@observablehq/plot@0.6/+esm")
plotWidth = Math.min(width, 1100)
petfood = [
{month: "Ян 24", i: 1, revenue: 5314, year: 2024},
{month: "Фев 24", i: 2, revenue: 5220, year: 2024},
{month: "Мар 24", i: 3, revenue: 5104, year: 2024},
{month: "Апр 24", i: 4, revenue: 5008, year: 2024},
{month: "Май 24", i: 5, revenue: 4944, year: 2024},
{month: "Юни 24", i: 6, revenue: 4693, year: 2024},
{month: "Юли 24", i: 7, revenue: 4565, year: 2024},
{month: "Авг 24", i: 8, revenue: 4854, year: 2024},
{month: "Сеп 24", i: 9, revenue: 5068, year: 2024},
{month: "Окт 24", i: 10, revenue: 5500, year: 2024},
{month: "Ное 24", i: 11, revenue: 5700, year: 2024},
{month: "Дек 24", i: 12, revenue: 6498, year: 2024},
{month: "Ян 25", i: 13, revenue: 6751, year: 2025},
{month: "Фев 25", i: 14, revenue: 6493, year: 2025},
{month: "Мар 25", i: 15, revenue: 6359, year: 2025},
{month: "Апр 25", i: 16, revenue: 6145, year: 2025},
{month: "Май 25", i: 17, revenue: 6019, year: 2025},
{month: "Юни 25", i: 18, revenue: 5804, year: 2025},
{month: "Юли 25", i: 19, revenue: 5728, year: 2025},
{month: "Авг 25", i: 20, revenue: 6178, year: 2025},
{month: "Сеп 25", i: 21, revenue: 6705, year: 2025},
{month: "Окт 25", i: 22, revenue: 7778, year: 2025},
{month: "Ное 25", i: 23, revenue: 8189, year: 2025},
{month: "Дек 25", i: 24, revenue: 8883, year: 2025}
]
// Simple linear regression for trendline
n = petfood.length
sumX = petfood.reduce((s, d) => s + d.i, 0)
sumY = petfood.reduce((s, d) => s + d.revenue, 0)
sumXY = petfood.reduce((s, d) => s + d.i * d.revenue, 0)
sumX2 = petfood.reduce((s, d) => s + d.i * d.i, 0)
slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX)
intercept = (sumY - slope * sumX) / n
trendData = petfood.map(d => ({...d, trend: intercept + slope * d.i}))
Plot.plot({
width: plotWidth,
height: 340,
marginRight: 40,
marginBottom: 40,
style: {fontSize: "13px", fontFamily: "Inter, sans-serif"},
title: "Приходите на ПетФууд растат, но с вълни — тренд, сезонност и шум",
subtitle: "Общ месечен приход (лв.), ян. 2024 – дек. 2025",
x: {label: null, tickRotate: -45, domain: petfood.map(d => d.month)},
y: {label: "Приход (лв.)", grid: true, domain: [4000, 9500]},
color: {legend: false},
marks: [
Plot.rectY([{x1: 12.5, x2: 24.5, y1: 4000, y2: 9500}], {
x1: d => "Ян 25", x2: d => "Дек 25", y1: 4000, y2: 9500, fill: "#e0f2fe", fillOpacity: 0.4
}),
Plot.line(trendData, {x: "month", y: "trend", stroke: "#dc2626", strokeWidth: 2.5, strokeDasharray: "8,4"}),
Plot.lineY(petfood, {x: "month", y: "revenue", stroke: "#2563eb", strokeWidth: 2.5, curve: "catmull-rom"}),
Plot.dot(petfood, {x: "month", y: "revenue", fill: d => d.year === 2025 ? "#2563eb" : "#94a3b8", r: 4.5, tip: true}),
Plot.text([{x: "Юли 24", y: 4350}], { x: "x", y: "y", text: d => "↓ Лятно дъно", fill: "#94a3b8", fontSize: 11, fontWeight: "bold" }),
Plot.text([{x: "Дек 25", y: 9350}], { x: "x", y: "y", text: d => "↑ Зимен пик", fill: "#2563eb", fontSize: 11, fontWeight: "bold" }),
Plot.text([{x: "Мар 25", y: 9200}], { x: "x", y: "y", text: d => "Старт на доставки по домовете →", fill: "#0284c7", fontSize: 11, fontWeight: "bold" }),
Plot.text([{x: "Авг 24", y: 9200}], { x: "x", y: "y", text: d => "── тренд линия", fill: "#dc2626", fontSize: 11 }),
]
})