KT3 — Частина II (Ініціалізація Панелі Приладів)

pic

Фото Roger Ce на Unsplash

Час додати кольору до цього проєкту і почати втілювати деякі з концептів, обговорених у попередньому пості. Ми створимо нашу аплікацію, яка зможе візуалізувати та використовувати ресурси з нашого API. Почнемо!

Для фронтенд-технологій ми вибрали React, оскільки він залишається однією з найпоширеніших технологій у галузі і надає нам велику гнучкість. Як фреймворк ми використовуватимемо NextJS; ідея полягає в тому, щоб почати створювати нашу панель управління простим способом, а згодом подивимося, чи є це найбільш підходящим підходом для нашої аплікації.

Для початку ми створимо нашу аплікацію за допомогою команди npx create-next-app@latest

npx create-next-app@latest  
Необхідно встановити наступні пакети:  
[email protected]  
Продовжити? (y) y  

✔ Як називатиметься ваш проєкт? … app  
✔ Бажаєте використовувати TypeScript? … Ні* / Так  
✔ Бажаєте використовувати ESLint? … Ні / Так*  
✔ Бажаєте використовувати Tailwind CSS? … Ні / Так*  
✔ Бажаєте розмістити код в директорії `src/`? … Ні* / Так  
✔ Бажаєте використовувати App Router? (рекомендовано) … Ні / Так*  
✔ Бажаєте використовувати Turbopack для next dev? … Ні / Так*  
✔ Бажаєте налаштувати псевдоніми імпортів (@/* за замовчуванням)? … Ні* / Так

Наразі ми використовуватимемо JavaScript замість TypeScript, хоча в майбутньому це може змінитись. Для стилізації ми працюватимемо з Tailwind, щоб спростити розробку компонентів. Тепер, коли у нас є базова NextJS аплікація, наступний крок — додати її до нашого docker-compose, щоб вона запускалася разом з усією інфраструктурою.

app:  
 container_name: app  
 build:  
 context: ./app  
 dockerfile: Dockerfile  
 env_file: app/.env  
 volumes:  
 - ./app:/home/app  
 - /app/node_modules  
 command: "npm run dev"  
 environment:  
 - NODE_ENV=development  
 ports:  
 - '3000:3000'  
 networks:  
 - kt3-net

Давайте трохи очистимо проєкт, щоб почати з макету у стилі Dashboard. Для цього ми створимо папку Dashboard та компонент для Sidebar.
Для Sidebar ми використаємо наступний код:

// app/app/components/Sidebar.js  
import Link from "next/link";  

export default function Sidebar() {  
 return (  

KT3    
Entries
Accounts
Account Groups
    )   } ```  Тепер, в папці **_dashboard_**, ми створимо головну сторінку з її макетом.  

// app/app/(dashboard)/layout.js
import "../globals.css";
import Sidebar from "@/app/components/Sidebar";

export const metadata = {
title: "Kt3 App",
description: "KT3 App Dashboard",
};

export default function RootLayout({children}) {
return (
{children}
);
}
```

Це наша початкова сторінка, простий компонент, який відображає заголовок Dashboard зі стилями Tailwind.

// app/app/(dashboard)/page.js  
 export default function Home() {  
    return (    
        Dashboard    
    );  
 }  

Тепер нам потрібні сторінки для наших перших моделей (Account Group, Account, Entry). Наразі ми додамо лише заголовки моделей, щоб перевірити, чи правильно працюють маршрути. До цього моменту ми створили наступні файли:

.   
 ├── components  
 │ └── sidebar.js  
 ├── (dashboard)  
 │ ├── account-groups  
 │ │ └── page.js  
 │ ├── accounts  
 │ │ └── page.js  
 │ ├── entries  
 │ │ └── page.js  
 │ ├── layout.js  
 │ └── page.js  
 ├── favicon.ico  
 └── globals.css  

Щоб додати кольору та зв'язати з попереднім дописом, ми протестуємо графік, що підсумовує кожну з моделей. Для цього використаємо одну з моїх улюблених бібліотек: Highcharts.

npm install highcharts --save  

Після того, як бібліотеку встановлено, ми створимо перший запит для отримання загальної кількості Account Groups.

Застереження
Тільки зараз я зрозумів, що не оновив попередній пост з цим кінцевим пунктом.

Тепер, для нашого запиту, ми спробуємо більш комплексний підхід до здійснення запитів, подібно до того, як це працює в SWR. Мета тут — зрозуміти, як обробляти обіцянки та помилки.
Для цього ми використаємо функцію для управління нашими запитами:

// app/app/utils/fetchData.js  
function getSuspender(promise) {   
 let status = 'pending';   
 let result;   
 let suspender = promise.then(   
 (response) => {   
 status = 'success';   
 result = response;   
 },   
 (error) => {   
 status = 'error';   
 result = error;   
 }   
 );   

 const read = () => {   
 switch (status) {   
 case 'pending':   
 throw suspender;   
 case 'error':   
 throw result;   
 case 'success':   
 return result;   
 }   
 }   

 return { read };   
}   

export default function fetchData(url) {  
 const promise = fetch(url)  
 .then((response) => {  
 if (!response.ok) {  
 throw new Error(`HTTP error! status: ${response.status}`);  
 }  
 return response.json();  
 })  
 .then((data) => data);  

 return getSuspender(promise);  
}

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

Перший графік, який ми створимо, буде стовпчиковим графіком для кожної групи рахунків:

// app/app/components/BarChart.js  
"use client";  

import React from "react";  
import Highcharts from "highcharts";  
import {useEffect} from "react";  

export default function BarChart({data}) {  
 let categories = [];  
 let series = [];  

 for (let key in data) {  
 categories.push(data[key].name);  
 series.push(data[key].amount);  
 }  

 useEffect(() => {  
 Highcharts.chart("basic-bar-chart", {  
 chart: {  
 type: 'column'  
 },  
 title: {  
 text: 'Accrued expenses by Account Group'  
 },  
 xAxis: {  
 categories: categories  
 },  
 yAxis: [{  
 min: 0,  
 title: {  
 text: 'Expends (MXN)'  
 }  
 }],  
 legend: {  
 shadow: false  
 },  
 tooltip: {  
 shared: true  
 },  
 plotOptions: {  
 column: {  
 grouping: false,  
 shadow: false,  
 borderWidth: 0  
 }  
 },  
 series: [{  
 name: 'Amount',  
 color: 'rgba(165,170,217,1)',  
 data: series,  
 pointPadding: 0.3,  
 pointPlacement: -0.2  
 }]  
 });  
 }, []);  

 return  
;   }  

Тепер давайте створимо Кругову діаграму для відображення розподілу Account Groups (груп рахунків) відносно їх загальних витрат.

// app/app/components/PieChart.js  
"use client";  

import React from 'react';  
import Highcharts from 'highcharts';  
import {useEffect} from "react";  

export default function PieChart({data}) {  
 let series = []  
 for (let key in data) {  
 series.push([data[key].name, data[key].amount])  
 }  

 useEffect(() => {  
 Highcharts.chart('pie-chart', {  
 chart: {  
 type: 'pie',  
 },  
 title: {  
 text: 'Distribution of expenses by account group'  
 },  
 series: [  
 {  
 name: 'Account Groups',  
 data: series  
 }  
 ]  
 })  
 }, [])  

 return (  
 )  
}  

Для завершення цієї сторінки ми додамо таблицю, в якій будуть перелічені Account Groups (групи рахунків) з можливістю взаємодії з кожною з них (Оновлення та Видалення).

// app/components/BasicTable.js  
"use client";  

export default function BasicTable({columns, dataColumns, data, actions}) {  
 return (  
 {columns.map((col, index) => (        ))}  
 {data ? data.map((row, rowIndex) => (  
 {dataColumns.map((col, colIndex) => (        ))}  
 {actions && 
{col}  
{row[col]}  
{actions.update &&  

}  
 {actions.delete &&   



 }  
 }  

 )) :   
 Empty  
 }  



 );  
}

На даний момент у нас є головна сторінка для Account Groups (груп рахунків), яка виглядає ось так:

// app/app/(dashboard)/account-groups/page.js  
"use client";  

import BarChart from "@/app/components/BarChart";  
import PieChart from "@/app/components/PieChart";  
import BasicTable from "@/app/components/BasicTable";  
import {Suspense} from "react";  
import fetchData from "@/app/utils/fetchData";  
import Link from "next/link";  
import MainTitle from "@/app/components/MainTitle";  

const apiDataTotal = fetchData("http://localhost:7000/api/analytics/account_groups_total");  
const apiData = fetchData("http://localhost:7000/api/account_groups");  

export default function Page() {  
 const dataTotal = apiDataTotal.read();  
 const data = apiData.read();  

 return (  
 <>  

Loading...
}>                    
Loading...
}>            
            );  
}  

Для завершення цієї статті, ми додамо кнопку, яка дозволить нам додавати Account Groups (групи рахунків).

    Create Account Group       

Тепер у нас є щось функціональне, що починає набувати форми та кольору.
pic

Наступним кроком ми створимо форму для обробки запиту на створення Account Groups (груп рахунків).

// app/app/components/AccountGroupForm.js  
"use client";  

import {useState, useRef} from "react";  

export default function AccountGroupForm() {  
 const [accountGroup, setAccountGroup] = useState({  
 name: "",  
 });   

 const form = useRef(null);   
 function handleChange(event) {  
 setAccountGroup({  
 ...accountGroup,  

 });  
 }  

 async function handleSubmit(event) {  
 event.preventDefault();   

 fetch(  
 "http://localhost:7000/api/account_groups", {  
 method: "POST",  
 headers: {  
 "Content-Type": "application/json",  
 },  
 body: JSON.stringify(accountGroup),  
 }).then((res) => res.json()).then(() => {  
 setAccountGroup({  
 name: "",  
 })  
 window.location.reload();  
 });  
 }  

 return (
Name            
    Create        
    );   } ```  Власне, ми маємо реактивну форму, яка надсилає запит після оцінки її вмісту.
На даний момент ми не реалізовуватимемо валідацію полів; це стане частиною подальшої роботи над проєктом.

Далі ми створимо папку з назвою **_create_**, де розмістимо нашу сторінку для додавання нових **_Account Groups_**. На цій сторінці ми викличемо нашу форму.

// app/app/(dashboard)/account-groups/create/page.js
import AccountGroupForm from "@/app/components/AccountGroupForm";
import MainTitle from "@/app/components/MainTitle";

export default function Page() {
return (

)   } ```  ![pic](https://drive.javascript.org.ua/91f2ede3fc1_UXMv4wjVadykGSrb0_R_rA_gif)  

Висновок

Ми почали інтеграцію API з клієнтською частиною нашого проєкту. Ще багато роботи попереду: додавання нових функціональностей, покращення користувацького досвіду та реалізація валідацій між бекендом і фронтендом.

Наразі ми зосередимося на наступних кроках і продовжимо ділитися вдосконаленнями в міру розвитку проєкту. Якщо у вас є пропозиції чи покращення для коду, не соромтесь залишити їх у коментарях.

Домашнє завдання

  • Створити форми для Accounts і Entries.
  • Реалізувати Breadcrumb для покращення навігації.
  • Додати Toast для повідомлень і сповіщень.
  • Покращити стилі та дизайн.

Наступні кроки

  • Модель користувача та аутентифікація
  • Логи та помилки
  • Метрики (Prometheus, Grafana, Kibana)
  • Кешування та пошук (Redis і Elastic)

Частина I

Джерело коду

## GitHub - arturocuicas/KT3 ### Пожертвуйте на розвиток arturocuicas/KT3, створивши акаунт на GitHub. github.com

Посилання

## React ### React — бібліотека для створення інтерфейсів користувача для веб та мобільних додатків. Створюйте інтерфейси користувача з окремих частин, званих… react.dev

## Next.js від Vercel - Рамка для React ### Продуктові React-додатки, що масштабуються. Провідні компанії світу використовують Next.js від Vercel для створення статичних і… nextjs.org

## Highcharts - Інтерактивна бібліотека для створення графіків для розробників ### Створюйте інтерактивну візуалізацію даних для веб і мобільних проєктів за допомогою Highcharts Core, Highcharts Stock, Highcharts… www.highcharts.com

## Tailwind CSS - Швидко створюйте сучасні вебсайти, не залишаючи HTML. ### Tailwind CSS — це CSS-фреймворк для швидкої розробки сучасних вебсайтів без необхідності покидати ваш HTML. tailwindcss.com

Перекладено з: KT3 — Part II (Init Dashboard)

Leave a Reply

Your email address will not be published. Required fields are marked *