From 7538c18624b3eb71f24a33856b1f5c0d96091472 Mon Sep 17 00:00:00 2001 From: vinix Date: Thu, 16 Oct 2025 15:36:01 +0700 Subject: [PATCH] feat: convert line chart data to table format and enhance filtering options in IndexReport --- src/pages/history/report/IndexReport.jsx | 339 +++++++++++++++---- src/pages/history/trending/IndexTrending.jsx | 280 ++++----------- 2 files changed, 339 insertions(+), 280 deletions(-) diff --git a/src/pages/history/report/IndexReport.jsx b/src/pages/history/report/IndexReport.jsx index 4a64fcc..4a26478 100644 --- a/src/pages/history/report/IndexReport.jsx +++ b/src/pages/history/report/IndexReport.jsx @@ -1,116 +1,305 @@ import React, { memo, useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb'; -import { Typography, Table } from 'antd'; +import { Typography, Table, Card, Select, DatePicker, Button, Row, Col } from 'antd'; +import { FileTextOutlined } from '@ant-design/icons'; +import { decryptData } from '../../../components/Global/Formatter'; +import dayjs from 'dayjs'; const { Text } = Typography; -// Mock Data -const initialData = [ +// Line Chart Data (same as IndexTrending) converted to table format +const lineChartData = [ { - key: '1', - plantSubSection: 'Section A', - device: 'Device 1', - errorCode: 'E-101', - status: 'Warning', + id: 'Compressor Section 1', + color: '#FF6B4A', + data: [ + { x: 'Jan', y: 15 }, + { x: 'Feb', y: 18 }, + { x: 'Mar', y: 17 }, + { x: 'Apr', y: 24 }, + { x: 'Mei', y: 21 }, + { x: 'Jun', y: 19 }, + { x: 'Jul', y: 28 }, + { x: 'Agu', y: 26 }, + { x: 'Sep', y: 22 }, + { x: 'Okt', y: 25 }, + ], }, { - key: '2', - plantSubSection: 'Section B', - device: 'Device 2', - errorCode: 'E-102', - status: 'Alarm', + id: 'Compressor Section 2', + color: '#4ECDC4', + data: [ + { x: 'Jan', y: 12 }, + { x: 'Feb', y: 14 }, + { x: 'Mar', y: 19 }, + { x: 'Apr', y: 21 }, + { x: 'Mei', y: 22 }, + { x: 'Jun', y: 20 }, + { x: 'Jul', y: 19 }, + { x: 'Agu', y: 21 }, + { x: 'Sep', y: 18 }, + { x: 'Okt', y: 20 }, + ], }, { - key: '3', - plantSubSection: 'Section C', - device: 'Device 3', - errorCode: 'E-103', - status: 'Done', - }, - { - key: '4', - plantSubSection: 'Section A', - device: 'Device 4', - errorCode: 'E-104', - status: 'Warning', + id: 'Compressor Section 3', + color: '#FFE66D', + data: [ + { x: 'Jan', y: 8 }, + { x: 'Feb', y: 10 }, + { x: 'Mar', y: 12 }, + { x: 'Apr', y: 15 }, + { x: 'Mei', y: 18 }, + { x: 'Jun', y: 20 }, + { x: 'Jul', y: 22 }, + { x: 'Agu', y: 21 }, + { x: 'Sep', y: 19 }, + { x: 'Okt', y: 26 }, + ], }, ]; const IndexReport = memo(function IndexReport() { const navigate = useNavigate(); const { setBreadcrumbItems } = useBreadcrumb(); - const [data, setData] = useState(initialData); + + const [plantSubSection, setPlantSubSection] = useState('Semua Plant'); + const [startDate, setStartDate] = useState(dayjs('2025-09-30')); + const [endDate, setEndDate] = useState(dayjs('2025-10-09')); + const [periode, setPeriode] = useState('Bulanan'); + const [userRole, setUserRole] = useState(null); + const [roleLevel, setRoleLevel] = useState(null); useEffect(() => { const token = localStorage.getItem('token'); if (token) { + // Get user data and role + let userData = null; + const sessionData = localStorage.getItem('session'); + if (sessionData) { + userData = decryptData(sessionData); + } else { + const userRaw = localStorage.getItem('user'); + if (userRaw) { + try { + userData = { user: JSON.parse(userRaw) }; + } catch (e) { + console.error('Error parsing user data:', e); + } + } + } + + if (userData?.user) { + setUserRole(userData.user.role_name); + setRoleLevel(userData.user.role_level); + } + setBreadcrumbItems([ - { title: • History }, - { title: Report } + { + title: ( + + • History + + ), + }, + { + title: ( + + Report + + ), + }, ]); } else { navigate('/signin'); } }, []); - const getTitleStyle = (statusName) => { - let backgroundColor; - switch (statusName.toLowerCase()) { - case 'done': - backgroundColor = '#52c41a'; // green - break; - case 'warning': - backgroundColor = '#faad14'; // orange - break; - case 'alarm': - backgroundColor = '#f5222d'; // red - break; - case 'critical': - backgroundColor = '#000000'; // black - break; - default: - backgroundColor = 'transparent'; - } - return { - backgroundColor, - color: '#fff', - padding: '2px 8px', - borderRadius: '4px', - display: 'inline-block' - }; + const handleReset = () => { + setPlantSubSection('Semua Plant'); + setStartDate(dayjs('2025-09-30')); + setEndDate(dayjs('2025-10-09')); + setPeriode('Bulanan'); }; + // Check if user has permission to view data (all except guest) + const canViewData = userRole && userRole !== 'guest'; + + // Convert chart data to table format + const convertToTableData = () => { + return lineChartData.map((section, index) => { + const rowData = { + key: index, + section: section.id, + color: section.color, + }; + + // Add each month's data as a column + section.data.forEach((point) => { + rowData[point.x] = point.y; + }); + + return rowData; + }); + }; + + const tableData = convertToTableData(); + + // Create dynamic columns based on months + const months = lineChartData[0]?.data.map((point) => point.x) || []; + const columns = [ { title: 'Plant Sub Section', - dataIndex: 'plantSubSection', - key: 'plantSubSection', - }, - { - title: 'Device', - dataIndex: 'device', - key: 'device', - }, - { - title: 'Error Code', - dataIndex: 'errorCode', - key: 'errorCode', - }, - { - title: 'Status', - dataIndex: 'status', - key: 'status', - render: (status) => ( - {status} + dataIndex: 'section', + key: 'section', + fixed: 'left', + width: 200, + render: (text, record) => ( +
+
+ {text} +
), }, + ...months.map((month) => ({ + title: month, + dataIndex: month, + key: month, + align: 'center', + width: 80, + render: (value) => {value}, + })), ]; return ( -
- - + +
+ {/* Filter Section */} + +
+ + ☰ Filter Data + +
+ +
+
+ + Plant Sub Section + + +
+ + + + + + + + + + + + + {/* Table Section */} + {!canViewData ? ( + + + Anda tidak memiliki akses untuk melihat data report. +
+ Silakan hubungi administrator untuk mendapatkan akses. +
+
+ ) : ( + +
+ + ☰ Trending Error per Plant Sub Section + +
+
+ + )} + + ); }); diff --git a/src/pages/history/trending/IndexTrending.jsx b/src/pages/history/trending/IndexTrending.jsx index ec81f95..f61edd7 100644 --- a/src/pages/history/trending/IndexTrending.jsx +++ b/src/pages/history/trending/IndexTrending.jsx @@ -1,10 +1,9 @@ import React, { memo, useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useBreadcrumb } from '../../../layout/LayoutBreadcrumb'; -import { Typography, Select, DatePicker, Button, Row, Col, Card, Statistic } from 'antd'; +import { Typography, Select, DatePicker, Button, Row, Col, Card } from 'antd'; import { ResponsiveLine } from '@nivo/line'; -import { ResponsivePie } from '@nivo/pie'; -import { FileTextOutlined, ToolOutlined, CheckCircleOutlined, ClockCircleOutlined } from '@ant-design/icons'; +import { FileTextOutlined } from '@ant-design/icons'; import { decryptData } from '../../../components/Global/Formatter'; import dayjs from 'dayjs'; import './trending.css'; @@ -47,8 +46,20 @@ const IndexTrending = memo(function IndexTrending() { } setBreadcrumbItems([ - { title: • History }, - { title: Trending }, + { + title: ( + + • History + + ), + }, + { + title: ( + + Trending + + ), + }, ]); } else { navigate('/signin'); @@ -138,16 +149,19 @@ const IndexTrending = memo(function IndexTrending() { return ( -
- {/* Filter Section */} - + {/* Filter Section */} +
- ☰ Filter Data + + ☰ Filter Data +
- Plant Sub Section + + Plant Sub Section +