lavoce #27
@@ -27,4 +27,29 @@ const getNotificationDetail = async (id) => {
|
|||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export { getAllNotification, getNotificationById, getNotificationDetail };
|
// Create new notification log
|
||||||
|
const createNotificationLog = async (data) => {
|
||||||
|
const response = await SendRequest({
|
||||||
|
method: 'post',
|
||||||
|
prefix: 'notification-log',
|
||||||
|
params: data,
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get notification logs by notification_error_id
|
||||||
|
const getNotificationLogByNotificationId = async (notificationId) => {
|
||||||
|
const response = await SendRequest({
|
||||||
|
method: 'get',
|
||||||
|
prefix: `notification-log/notification_error/${notificationId}`,
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
getAllNotification,
|
||||||
|
getNotificationById,
|
||||||
|
getNotificationDetail,
|
||||||
|
createNotificationLog,
|
||||||
|
getNotificationLogByNotificationId
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useParams, useNavigate } from 'react-router-dom';
|
import { useParams, useNavigate } from 'react-router-dom';
|
||||||
import { Layout, Card, Row, Col, Typography, Space, Button, Spin, Result, Input } from 'antd';
|
import { Layout, Card, Row, Col, Typography, Space, Button, Spin, Result, Input, message } from 'antd';
|
||||||
import {
|
import {
|
||||||
ArrowLeftOutlined,
|
ArrowLeftOutlined,
|
||||||
CloseCircleFilled,
|
CloseCircleFilled,
|
||||||
@@ -14,8 +14,9 @@ import {
|
|||||||
FilePdfOutlined,
|
FilePdfOutlined,
|
||||||
PlusOutlined,
|
PlusOutlined,
|
||||||
UserOutlined,
|
UserOutlined,
|
||||||
|
LoadingOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { getNotificationDetail } from '../../api/notification';
|
import { getNotificationDetail, createNotificationLog, getNotificationLogByNotificationId } from '../../api/notification';
|
||||||
import UserHistoryModal from '../notification/component/UserHistoryModal';
|
import UserHistoryModal from '../notification/component/UserHistoryModal';
|
||||||
import LogHistoryCard from '../notification/component/LogHistoryCard';
|
import LogHistoryCard from '../notification/component/LogHistoryCard';
|
||||||
|
|
||||||
@@ -38,12 +39,12 @@ const transformNotificationData = (apiData) => {
|
|||||||
description: apiData.message_error_issue || 'No details available',
|
description: apiData.message_error_issue || 'No details available',
|
||||||
timestamp: apiData.created_at
|
timestamp: apiData.created_at
|
||||||
? new Date(apiData.created_at).toLocaleString('id-ID', {
|
? new Date(apiData.created_at).toLocaleString('id-ID', {
|
||||||
day: '2-digit',
|
day: '2-digit',
|
||||||
month: '2-digit',
|
month: '2-digit',
|
||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
hour: '2-digit',
|
hour: '2-digit',
|
||||||
minute: '2-digit',
|
minute: '2-digit',
|
||||||
}) + ' WIB'
|
}) + ' WIB'
|
||||||
: 'N/A',
|
: 'N/A',
|
||||||
location: apiData.plant_sub_section_name || 'Location not specified',
|
location: apiData.plant_sub_section_name || 'Location not specified',
|
||||||
details: apiData.message_error_issue || 'No details available',
|
details: apiData.message_error_issue || 'No details available',
|
||||||
@@ -61,9 +62,9 @@ const transformNotificationData = (apiData) => {
|
|||||||
...activeSolution,
|
...activeSolution,
|
||||||
path_document: activeSolution.path_document
|
path_document: activeSolution.path_document
|
||||||
? activeSolution.path_document.replace(
|
? activeSolution.path_document.replace(
|
||||||
'/detail-notification/pdf/',
|
'/detail-notification/pdf/',
|
||||||
'/notification-detail/pdf/'
|
'/notification-detail/pdf/'
|
||||||
)
|
)
|
||||||
: activeSolution.path_document,
|
: activeSolution.path_document,
|
||||||
}, // Include the active solution data with fixed URL
|
}, // Include the active solution data with fixed URL
|
||||||
error_code: errorCodeData,
|
error_code: errorCodeData,
|
||||||
@@ -98,35 +99,77 @@ const NotificationDetailTab = () => {
|
|||||||
const [modalContent, setModalContent] = useState(null); // 'user', atau null
|
const [modalContent, setModalContent] = useState(null); // 'user', atau null
|
||||||
const [isAddingLog, setIsAddingLog] = useState(false);
|
const [isAddingLog, setIsAddingLog] = useState(false);
|
||||||
|
|
||||||
const logHistoryData = [
|
// Log history states
|
||||||
{
|
const [logHistoryData, setLogHistoryData] = useState([]);
|
||||||
id: 1,
|
const [logLoading, setLogLoading] = useState(false);
|
||||||
timestamp: '04-11-2025 11:55 WIB',
|
const [newLogDescription, setNewLogDescription] = useState('');
|
||||||
addedBy: {
|
const [submitLoading, setSubmitLoading] = useState(false);
|
||||||
name: 'Budi Santoso',
|
|
||||||
phone: '081122334455',
|
// Fetch log history from API
|
||||||
},
|
const fetchLogHistory = async (notifId) => {
|
||||||
description: 'Suhu sudah coba diturunkan, namun masih belum mencapai treshold aman.',
|
try {
|
||||||
},
|
setLogLoading(true);
|
||||||
{
|
const response = await getNotificationLogByNotificationId(notifId);
|
||||||
id: 2,
|
if (response && response.data) {
|
||||||
timestamp: '04-11-2025 11:45 WIB',
|
// Transform API data to component format
|
||||||
addedBy: {
|
const transformedLogs = response.data.map((log) => ({
|
||||||
name: 'John Doe',
|
id: log.notification_error_log_id,
|
||||||
phone: '081234567890',
|
timestamp: log.created_at
|
||||||
},
|
? new Date(log.created_at).toLocaleString('id-ID', {
|
||||||
description: 'Suhu sudah coba diturunkan, namun masih belum mencapai treshold aman.',
|
day: '2-digit',
|
||||||
},
|
month: '2-digit',
|
||||||
{
|
year: 'numeric',
|
||||||
id: 3,
|
hour: '2-digit',
|
||||||
timestamp: '04-11-2025 11:40 WIB',
|
minute: '2-digit',
|
||||||
addedBy: {
|
}) + ' WIB'
|
||||||
name: 'Jane Smith',
|
: 'N/A',
|
||||||
phone: '087654321098',
|
addedBy: {
|
||||||
},
|
name: log.contact_name || 'Unknown',
|
||||||
description: 'Suhu sudah coba diturunkan, namun masih belum mencapai treshold aman.',
|
phone: log.contact_phone || '',
|
||||||
},
|
},
|
||||||
];
|
description: log.notification_error_log_description || '',
|
||||||
|
}));
|
||||||
|
setLogHistoryData(transformedLogs);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error fetching log history:', err);
|
||||||
|
} finally {
|
||||||
|
setLogLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle submit new log
|
||||||
|
const handleSubmitLog = async () => {
|
||||||
|
if (!newLogDescription.trim()) {
|
||||||
|
message.warning('Mohon isi deskripsi log terlebih dahulu');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
setSubmitLoading(true);
|
||||||
|
const payload = {
|
||||||
|
notification_error_id: parseInt(notificationId),
|
||||||
|
notification_error_log_description: newLogDescription.trim(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await createNotificationLog(payload);
|
||||||
|
|
||||||
|
if (response && response.statusCode === 200) {
|
||||||
|
message.success('Log berhasil ditambahkan');
|
||||||
|
setNewLogDescription('');
|
||||||
|
setIsAddingLog(false);
|
||||||
|
// Refresh log history
|
||||||
|
fetchLogHistory(notificationId);
|
||||||
|
} else {
|
||||||
|
throw new Error(response?.message || 'Gagal menambahkan log');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error submitting log:', err);
|
||||||
|
message.error(err.message || 'Gagal menambahkan log');
|
||||||
|
} finally {
|
||||||
|
setSubmitLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchDetail = async () => {
|
const fetchDetail = async () => {
|
||||||
@@ -139,6 +182,9 @@ const NotificationDetailTab = () => {
|
|||||||
if (response && response.data) {
|
if (response && response.data) {
|
||||||
const transformedData = transformNotificationData(response.data);
|
const transformedData = transformNotificationData(response.data);
|
||||||
setNotification(transformedData);
|
setNotification(transformedData);
|
||||||
|
|
||||||
|
// Fetch log history
|
||||||
|
fetchLogHistory(notificationId);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Notification not found');
|
throw new Error('Notification not found');
|
||||||
}
|
}
|
||||||
@@ -343,7 +389,11 @@ const NotificationDetailTab = () => {
|
|||||||
|
|
||||||
{/* Kolom Kanan: Log History */}
|
{/* Kolom Kanan: Log History */}
|
||||||
<Col xs={24} lg={8}>
|
<Col xs={24} lg={8}>
|
||||||
<LogHistoryCard notificationData={notification} />
|
<LogHistoryCard
|
||||||
|
notificationData={notification}
|
||||||
|
logData={logHistoryData}
|
||||||
|
loading={logLoading}
|
||||||
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
@@ -408,7 +458,7 @@ const NotificationDetailTab = () => {
|
|||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
>
|
>
|
||||||
{notification.error_code?.solution &&
|
{notification.error_code?.solution &&
|
||||||
notification.error_code.solution.length > 0 ? (
|
notification.error_code.solution.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
{notification.error_code.solution
|
{notification.error_code.solution
|
||||||
.filter((sol) => sol.is_active) // Hanya tampilkan solusi yang aktif
|
.filter((sol) => sol.is_active) // Hanya tampilkan solusi yang aktif
|
||||||
@@ -482,7 +532,7 @@ const NotificationDetailTab = () => {
|
|||||||
</Card>
|
</Card>
|
||||||
) : null}
|
) : null}
|
||||||
{sol.type_solution === 'text' &&
|
{sol.type_solution === 'text' &&
|
||||||
sol.text_solution ? (
|
sol.text_solution ? (
|
||||||
<Card
|
<Card
|
||||||
size="small"
|
size="small"
|
||||||
bodyStyle={{
|
bodyStyle={{
|
||||||
@@ -543,7 +593,7 @@ const NotificationDetailTab = () => {
|
|||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
>
|
>
|
||||||
{notification.spareparts &&
|
{notification.spareparts &&
|
||||||
notification.spareparts.length > 0 ? (
|
notification.spareparts.length > 0 ? (
|
||||||
notification.spareparts.map((sparepart, index) => (
|
notification.spareparts.map((sparepart, index) => (
|
||||||
<Card
|
<Card
|
||||||
size="small"
|
size="small"
|
||||||
@@ -581,7 +631,7 @@ const NotificationDetailTab = () => {
|
|||||||
color:
|
color:
|
||||||
sparepart.sparepart_stok ===
|
sparepart.sparepart_stok ===
|
||||||
'Available' ||
|
'Available' ||
|
||||||
sparepart.sparepart_stok ===
|
sparepart.sparepart_stok ===
|
||||||
'available'
|
'available'
|
||||||
? '#52c41a'
|
? '#52c41a'
|
||||||
: '#ff4d4f',
|
: '#ff4d4f',
|
||||||
@@ -671,6 +721,9 @@ const NotificationDetailTab = () => {
|
|||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
rows={2}
|
rows={2}
|
||||||
placeholder="Tuliskan update penanganan di sini..."
|
placeholder="Tuliskan update penanganan di sini..."
|
||||||
|
value={newLogDescription}
|
||||||
|
onChange={(e) => setNewLogDescription(e.target.value)}
|
||||||
|
disabled={submitLoading}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@@ -678,11 +731,26 @@ const NotificationDetailTab = () => {
|
|||||||
type={isAddingLog ? 'primary' : 'dashed'}
|
type={isAddingLog ? 'primary' : 'dashed'}
|
||||||
size="small"
|
size="small"
|
||||||
block
|
block
|
||||||
icon={!isAddingLog && <PlusOutlined />}
|
icon={submitLoading ? <LoadingOutlined /> : (!isAddingLog && <PlusOutlined />)}
|
||||||
onClick={() => setIsAddingLog(!isAddingLog)}
|
onClick={isAddingLog ? handleSubmitLog : () => setIsAddingLog(true)}
|
||||||
|
loading={submitLoading}
|
||||||
|
disabled={submitLoading}
|
||||||
>
|
>
|
||||||
{isAddingLog ? 'Submit Log' : 'Add Log'}
|
{isAddingLog ? 'Submit Log' : 'Add Log'}
|
||||||
</Button>
|
</Button>
|
||||||
|
{isAddingLog && (
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
block
|
||||||
|
onClick={() => {
|
||||||
|
setIsAddingLog(false);
|
||||||
|
setNewLogDescription('');
|
||||||
|
}}
|
||||||
|
disabled={submitLoading}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</Space>
|
</Space>
|
||||||
</Card>
|
</Card>
|
||||||
{logHistoryData.map((log) => (
|
{logHistoryData.map((log) => (
|
||||||
|
|||||||
Reference in New Issue
Block a user