feat: add notification log creation and retrieval functionality
This commit is contained in:
@@ -27,4 +27,29 @@ const getNotificationDetail = async (id) => {
|
||||
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 { 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 {
|
||||
ArrowLeftOutlined,
|
||||
CloseCircleFilled,
|
||||
@@ -14,8 +14,9 @@ import {
|
||||
FilePdfOutlined,
|
||||
PlusOutlined,
|
||||
UserOutlined,
|
||||
LoadingOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { getNotificationDetail } from '../../api/notification';
|
||||
import { getNotificationDetail, createNotificationLog, getNotificationLogByNotificationId } from '../../api/notification';
|
||||
import UserHistoryModal from '../notification/component/UserHistoryModal';
|
||||
import LogHistoryCard from '../notification/component/LogHistoryCard';
|
||||
|
||||
@@ -38,12 +39,12 @@ const transformNotificationData = (apiData) => {
|
||||
description: apiData.message_error_issue || 'No details available',
|
||||
timestamp: apiData.created_at
|
||||
? new Date(apiData.created_at).toLocaleString('id-ID', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
}) + ' WIB'
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
}) + ' WIB'
|
||||
: 'N/A',
|
||||
location: apiData.plant_sub_section_name || 'Location not specified',
|
||||
details: apiData.message_error_issue || 'No details available',
|
||||
@@ -61,9 +62,9 @@ const transformNotificationData = (apiData) => {
|
||||
...activeSolution,
|
||||
path_document: activeSolution.path_document
|
||||
? activeSolution.path_document.replace(
|
||||
'/detail-notification/pdf/',
|
||||
'/notification-detail/pdf/'
|
||||
)
|
||||
'/detail-notification/pdf/',
|
||||
'/notification-detail/pdf/'
|
||||
)
|
||||
: activeSolution.path_document,
|
||||
}, // Include the active solution data with fixed URL
|
||||
error_code: errorCodeData,
|
||||
@@ -98,35 +99,77 @@ const NotificationDetailTab = () => {
|
||||
const [modalContent, setModalContent] = useState(null); // 'user', atau null
|
||||
const [isAddingLog, setIsAddingLog] = useState(false);
|
||||
|
||||
const logHistoryData = [
|
||||
{
|
||||
id: 1,
|
||||
timestamp: '04-11-2025 11:55 WIB',
|
||||
addedBy: {
|
||||
name: 'Budi Santoso',
|
||||
phone: '081122334455',
|
||||
},
|
||||
description: 'Suhu sudah coba diturunkan, namun masih belum mencapai treshold aman.',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
timestamp: '04-11-2025 11:45 WIB',
|
||||
addedBy: {
|
||||
name: 'John Doe',
|
||||
phone: '081234567890',
|
||||
},
|
||||
description: 'Suhu sudah coba diturunkan, namun masih belum mencapai treshold aman.',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
timestamp: '04-11-2025 11:40 WIB',
|
||||
addedBy: {
|
||||
name: 'Jane Smith',
|
||||
phone: '087654321098',
|
||||
},
|
||||
description: 'Suhu sudah coba diturunkan, namun masih belum mencapai treshold aman.',
|
||||
},
|
||||
];
|
||||
// Log history states
|
||||
const [logHistoryData, setLogHistoryData] = useState([]);
|
||||
const [logLoading, setLogLoading] = useState(false);
|
||||
const [newLogDescription, setNewLogDescription] = useState('');
|
||||
const [submitLoading, setSubmitLoading] = useState(false);
|
||||
|
||||
// Fetch log history from API
|
||||
const fetchLogHistory = async (notifId) => {
|
||||
try {
|
||||
setLogLoading(true);
|
||||
const response = await getNotificationLogByNotificationId(notifId);
|
||||
if (response && response.data) {
|
||||
// Transform API data to component format
|
||||
const transformedLogs = response.data.map((log) => ({
|
||||
id: log.notification_error_log_id,
|
||||
timestamp: log.created_at
|
||||
? new Date(log.created_at).toLocaleString('id-ID', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
}) + ' WIB'
|
||||
: 'N/A',
|
||||
addedBy: {
|
||||
name: log.contact_name || 'Unknown',
|
||||
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(() => {
|
||||
const fetchDetail = async () => {
|
||||
@@ -139,6 +182,9 @@ const NotificationDetailTab = () => {
|
||||
if (response && response.data) {
|
||||
const transformedData = transformNotificationData(response.data);
|
||||
setNotification(transformedData);
|
||||
|
||||
// Fetch log history
|
||||
fetchLogHistory(notificationId);
|
||||
} else {
|
||||
throw new Error('Notification not found');
|
||||
}
|
||||
@@ -343,7 +389,11 @@ const NotificationDetailTab = () => {
|
||||
|
||||
{/* Kolom Kanan: Log History */}
|
||||
<Col xs={24} lg={8}>
|
||||
<LogHistoryCard notificationData={notification} />
|
||||
<LogHistoryCard
|
||||
notificationData={notification}
|
||||
logData={logHistoryData}
|
||||
loading={logLoading}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
@@ -408,7 +458,7 @@ const NotificationDetailTab = () => {
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
{notification.error_code?.solution &&
|
||||
notification.error_code.solution.length > 0 ? (
|
||||
notification.error_code.solution.length > 0 ? (
|
||||
<>
|
||||
{notification.error_code.solution
|
||||
.filter((sol) => sol.is_active) // Hanya tampilkan solusi yang aktif
|
||||
@@ -482,7 +532,7 @@ const NotificationDetailTab = () => {
|
||||
</Card>
|
||||
) : null}
|
||||
{sol.type_solution === 'text' &&
|
||||
sol.text_solution ? (
|
||||
sol.text_solution ? (
|
||||
<Card
|
||||
size="small"
|
||||
bodyStyle={{
|
||||
@@ -543,7 +593,7 @@ const NotificationDetailTab = () => {
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
{notification.spareparts &&
|
||||
notification.spareparts.length > 0 ? (
|
||||
notification.spareparts.length > 0 ? (
|
||||
notification.spareparts.map((sparepart, index) => (
|
||||
<Card
|
||||
size="small"
|
||||
@@ -581,7 +631,7 @@ const NotificationDetailTab = () => {
|
||||
color:
|
||||
sparepart.sparepart_stok ===
|
||||
'Available' ||
|
||||
sparepart.sparepart_stok ===
|
||||
sparepart.sparepart_stok ===
|
||||
'available'
|
||||
? '#52c41a'
|
||||
: '#ff4d4f',
|
||||
@@ -671,6 +721,9 @@ const NotificationDetailTab = () => {
|
||||
<Input.TextArea
|
||||
rows={2}
|
||||
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'}
|
||||
size="small"
|
||||
block
|
||||
icon={!isAddingLog && <PlusOutlined />}
|
||||
onClick={() => setIsAddingLog(!isAddingLog)}
|
||||
icon={submitLoading ? <LoadingOutlined /> : (!isAddingLog && <PlusOutlined />)}
|
||||
onClick={isAddingLog ? handleSubmitLog : () => setIsAddingLog(true)}
|
||||
loading={submitLoading}
|
||||
disabled={submitLoading}
|
||||
>
|
||||
{isAddingLog ? 'Submit Log' : 'Add Log'}
|
||||
</Button>
|
||||
{isAddingLog && (
|
||||
<Button
|
||||
size="small"
|
||||
block
|
||||
onClick={() => {
|
||||
setIsAddingLog(false);
|
||||
setNewLogDescription('');
|
||||
}}
|
||||
disabled={submitLoading}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
)}
|
||||
</Space>
|
||||
</Card>
|
||||
{logHistoryData.map((log) => (
|
||||
|
||||
Reference in New Issue
Block a user