Реалізація roadmap-сторінки (публічна дорожня карта) на сайті

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація roadmap-сторінки (публічна дорожня карта) на сайті
Середня
~2-3 робочих дні
Часті питання

Наші компетенції:

Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Розроблення публічної сторінки дорожної карти

Публічна дорожна карта показує користувачам, що команда планує побудувати, що в процесі роботи та що готово. Це інструмент довіри та утримання — користувачі бачать, що їхні запити почуті. Реалізується як статична сторінка з даними з Notion, Linear, Jira або власної БД.

Джерела даних

Варіант 1: Notion як CMS для дорожної карти

// lib/roadmap.ts
import { Client } from '@notionhq/client';

const notion = new Client({ auth: process.env.NOTION_TOKEN });

export interface RoadmapItem {
  id:          string;
  title:       string;
  status:      'planned' | 'in_progress' | 'done';
  quarter:     string;  // 'Q1 2025'
  category:    string;
  votes:       number;
  description: string;
}

export async function getRoadmap(): Promise<RoadmapItem[]> {
  const response = await notion.databases.query({
    database_id: process.env.NOTION_ROADMAP_DB_ID!,
    filter: {
      property: 'Public',
      checkbox: { equals: true },
    },
    sorts: [{ property: 'Quarter', direction: 'ascending' }],
  });

  return response.results.map(page => ({
    id:          page.id,
    title:       page.properties.Name.title[0]?.plain_text ?? '',
    status:      page.properties.Status.select?.name?.toLowerCase().replace(' ', '_') as any,
    quarter:     page.properties.Quarter.select?.name ?? '',
    category:    page.properties.Category.select?.name ?? '',
    votes:       page.properties.Votes.number ?? 0,
    description: page.properties.Description.rich_text[0]?.plain_text ?? '',
  }));
}

Варіант 2: Власна база даних

// Модель RoadmapItem
Schema::create('roadmap_items', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('description')->nullable();
    $table->enum('status', ['planned', 'in_progress', 'done', 'cancelled'])->default('planned');
    $table->string('quarter')->nullable();   // 'Q2 2025'
    $table->string('category')->nullable();  // 'Performance', 'Mobile', 'API'
    $table->integer('sort_order')->default(0);
    $table->boolean('is_public')->default(true);
    $table->timestamps();
});

Frontend: Дошка Kanban

// components/Roadmap.tsx
const STATUS_COLUMNS = [
  { key: 'planned',     label: 'Запланировано', color: 'bg-gray-100' },
  { key: 'in_progress', label: 'В роботі',       color: 'bg-blue-100' },
  { key: 'done',        label: 'Готово',          color: 'bg-green-100' },
];

export function RoadmapBoard({ items }: { items: RoadmapItem[] }) {
  const grouped = STATUS_COLUMNS.map(col => ({
    ...col,
    items: items.filter(i => i.status === col.key),
  }));

  return (
    <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
      {grouped.map(col => (
        <div key={col.key}>
          <h3 className={`font-semibold px-3 py-2 rounded-t ${col.color}`}>
            {col.label} <span className="text-gray-500 font-normal">({col.items.length})</span>
          </h3>
          <div className="space-y-3 mt-3">
            {col.items.map(item => (
              <RoadmapCard key={item.id} item={item} />
            ))}
          </div>
        </div>
      ))}
    </div>
  );
}

function RoadmapCard({ item }: { item: RoadmapItem }) {
  return (
    <div className="bg-white border rounded-lg p-4 shadow-sm">
      {item.category && (
        <span className="text-xs bg-indigo-100 text-indigo-700 px-2 py-0.5 rounded-full">{item.category}</span>
      )}
      <h4 className="font-medium mt-2">{item.title}</h4>
      {item.description && <p className="text-sm text-gray-500 mt-1">{item.description}</p>}
      {item.quarter && <p className="text-xs text-gray-400 mt-2">{item.quarter}</p>}
    </div>
  );
}

Фільтрація та пошук

// Фільтр на стороні клієнта без перезавантаження сторінки
const [filter, setFilter] = useState<string>('all');
const [search, setSearch]  = useState('');

const visible = items.filter(item =>
  (filter === 'all' || item.category === filter) &&
  (search === '' || item.title.toLowerCase().includes(search.toLowerCase()))
);

ISR-кэширование для Next.js

// pages/roadmap.tsx
export const getStaticProps: GetStaticProps = async () => {
  const items = await getRoadmap();
  return {
    props: { items },
    revalidate: 3600,  // Перегенерація раз на годину
  };
};

Сповіщення підписників про оновлення

Коли статус змінюється на done, автоматично відправляйте листи користувачам, які підписалися на цю функцію:

public function handle(RoadmapItemStatusChanged $event): void
{
    if ($event->item->status !== 'done') return;

    $subscribers = $event->item->subscribers()->with('user')->get();
    foreach ($subscribers as $sub) {
        Mail::to($sub->user->email)->queue(new RoadmapItemCompletedMail($event->item));
    }
}

Часовий графік

Публічна дорожна карта з Notion-бэкендом або власною БД, фільтрами та ISR-кешем: 3–4 робочих дні.