Розробка кастомних модулів Directus

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

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

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

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

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка кастомних модулів Directus
Середня
~3-5 робочих днів
Часті питання

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

Етапи розробки
Останні роботи
  • 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

Розробка кастомних модулів Directus

Module Extension — повнофункціональна сторінка Vue 3 в панелі адміністратора Directus з власним маршрутом та іконкою в навігації. Використовується для кастомних дашбордів, специфічного бізнес-інструментарію, інтеграцій, яким потрібен UI.

Структура модуля

npx create-directus-extension@latest
# Type: module
# Name: sales-dashboard
directus-extension-module-sales-dashboard/
├── src/
│   ├── index.ts          # Реєстрація модуля
│   └── module.vue        # Основний компонент
├── package.json
└── tsconfig.json

Реєстрація модуля

// src/index.ts
import ModuleComponent from './module.vue'

export default {
  id: 'sales-dashboard',        // унікальний ID → маршрут /sales-dashboard
  name: 'Sales Dashboard',
  icon: 'bar_chart',
  routes: [
    {
      path: '',
      component: ModuleComponent,
    },
    {
      path: ':orderId',
      component: () => import('./views/OrderDetail.vue'),
      props: true,
    },
  ],
}

Компонент Dashboard

<!-- src/module.vue -->
<template>
  <private-view title="Sales Dashboard">
    <template #headline>Аналітика продажів</template>
    <template #title-outer:prepend>
      <v-button rounded icon secondary @click="refresh">
        <v-icon name="refresh" />
      </v-button>
    </template>
    <template #actions>
      <v-button @click="exportData">
        <v-icon name="download" left />
        Експорт
      </v-button>
    </template>

    <!-- Основний контент -->
    <div class="dashboard-grid">
      <div class="stat-card" v-for="stat in stats" :key="stat.label">
        <div class="stat-value">{{ stat.value }}</div>
        <div class="stat-label">{{ stat.label }}</div>
        <div class="stat-change" :class="stat.change > 0 ? 'positive' : 'negative'">
          {{ stat.change > 0 ? '+' : '' }}{{ stat.change }}%
        </div>
      </div>
    </div>

    <div class="orders-table">
      <v-table
        :headers="headers"
        :items="orders"
        :loading="loading"
        show-resize
        @click:row="openOrder"
      />
    </div>
  </private-view>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useApi, useRouter } from '@directus/extensions-sdk'

const api = useApi()
const router = useRouter()

const loading = ref(true)
const stats = ref<any[]>([])
const orders = ref<any[]>([])

const headers = [
  { text: 'ID', value: 'id', width: 80 },
  { text: 'Клієнт', value: 'customer_email' },
  { text: 'Сума', value: 'total', width: 120 },
  { text: 'Статус', value: 'status', width: 120 },
  { text: 'Дата', value: 'date_created', width: 160 },
]

async function fetchData() {
  loading.value = true
  try {
    const [ordersRes, statsRes] = await Promise.all([
      api.get('/items/orders', {
        params: {
          sort: '-date_created',
          limit: 50,
          fields: ['id', 'customer_email', 'total', 'status', 'date_created'],
        },
      }),
      api.get('/custom/reports/sales'),
    ])

    orders.value = ordersRes.data.data
    stats.value = [
      { label: 'Замовлення сьогодні', value: statsRes.data.today, change: statsRes.data.todayChange },
      { label: 'Дохід за місяць', value: `${statsRes.data.monthRevenue.toLocaleString()} ₴`, change: statsRes.data.revenueChange },
    ]
  } finally {
    loading.value = false
  }
}

function openOrder({ item }: { item: any }) {
  router.push(`/sales-dashboard/${item.id}`)
}

async function exportData() {
  const response = await api.post('/custom/reports/export', {
    collection: 'orders',
    format: 'csv',
  }, { responseType: 'blob' })

  const url = URL.createObjectURL(new Blob([response.data]))
  const a = document.createElement('a')
  a.href = url
  a.download = 'orders.csv'
  a.click()
}

function refresh() { fetchData() }

onMounted(fetchData)
</script>

<style scoped>
.dashboard-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 16px; padding: 24px; }
.stat-card { background: var(--background-page); border: 1px solid var(--border-normal); border-radius: 8px; padding: 16px; }
.stat-value { font-size: 28px; font-weight: 700; }
.stat-label { color: var(--foreground-subdued); font-size: 13px; }
.positive { color: var(--success); }
.negative { color: var(--danger); }
.orders-table { padding: 0 24px 24px; }
</style>

Використання Directus API з модуля

// Доступ до стандартних сервісів Directus
const api = useApi()         // HTTP клієнт (Axios)
const stores = useStores()   // Pinia stores Directus
const router = useRouter()   // Vue Router

// Створення запису
await api.post('/items/articles', { data: { title: 'New', status: 'draft' } })

// Стандартні компоненти Directus UI
// <v-button>, <v-input>, <v-select>, <v-table>, <v-icon>, <v-dialog>
// <private-view> — обгортка сторінки з боковою навігацією

Терміни

Розробка кастомного модуля (дашборд з таблицями та експортом) — 2–4 дні.