Enhance AI Insight with new state management and PDF export functionality. Added selectedArea state to App for better context in reports. Introduced new markdown files for documentation on AI Insight improvements and setup instructions. Updated package dependencies and fixed TypeScript errors for improved stability.
CI / lint-and-test (push) Canceled after 0s

This commit is contained in:
Alberto-Audrix committed 2026-08-11 09:19:06 +07:00
1 parent a8b49374f1
commit 2a627a2c3f
84 files changed
+8415 -2692

No files matched your search

+14 -14
View File
@@ -226,10 +226,11 @@ async function fetchLiveIotSensorRange(
});
// Extract time part (format is "HH:MM" or "MM/DD/YYYY, HH:MM")
const timePart = wibTimeString.includes(',') ? wibTimeString.split(', ')[1] : wibTimeString;
const timePart =
(wibTimeString.includes(',') ? wibTimeString.split(', ')[1] : wibTimeString) ?? '';
// Round to 5-minute intervals for aggregation
const [hourStr, minuteStr] = timePart.split(':');
const [hourStr = '0', minuteStr = '0'] = timePart.split(':');
const hour = parseInt(hourStr, 10);
const minute = Math.floor(parseInt(minuteStr, 10) / 5) * 5;
@@ -246,13 +247,12 @@ async function fetchLiveIotSensorRange(
[key: string]: { Suhu: number[]; Kelembapan: number[]; Amonia: number[] };
} = {};
transformedData.forEach((item) => {
if (!aggregated[item.time]) {
aggregated[item.time] = { Suhu: [], Kelembapan: [], Amonia: [] };
}
aggregated[item.time].Suhu.push(item.Suhu);
aggregated[item.time].Kelembapan.push(item.Kelembapan);
aggregated[item.time].Amonia.push(item.Amonia);
transformedData.forEach((item: (typeof transformedData)[number]) => {
const bucket =
aggregated[item.time] ?? (aggregated[item.time] = { Suhu: [], Kelembapan: [], Amonia: [] });
bucket.Suhu.push(item.Suhu);
bucket.Kelembapan.push(item.Kelembapan);
bucket.Amonia.push(item.Amonia);
});
// Calculate averages for each time slot
@@ -265,8 +265,8 @@ async function fetchLiveIotSensorRange(
// Sort by time
result.sort((a, b) => {
const [aHour, aMin] = a.time.split(':').map(Number);
const [bHour, bMin] = b.time.split(':').map(Number);
const [aHour = 0, aMin = 0] = a.time.split(':').map(Number);
const [bHour = 0, bMin = 0] = b.time.split(':').map(Number);
return aHour * 60 + aMin - (bHour * 60 + bMin);
});
@@ -327,7 +327,7 @@ function transformFeedSackData(apiData: any[]): {
.split('_')
.slice(0, 2)
.join(' ')
.replace(/^\w/, (c) => c.toUpperCase());
.replace(/^\w/, (c: string) => c.toUpperCase());
cameraData.records.forEach((record: any) => {
entries.push({
@@ -829,7 +829,7 @@ export const apiClient = {
mode: 'yesterday',
range_size: 50.0,
data: {
tanggal: new Date().toISOString().split('T')[0],
tanggal: new Date().toISOString().split('T')[0] ?? '',
total_predictions: 150,
total_chicken_count: initialWeightDistribution.reduce((sum, item) => sum + item.count, 0),
distribusi: initialWeightDistribution.map((item) => ({
@@ -958,7 +958,7 @@ export const apiClient = {
);
mockDataArray.push({
tanggal: currentDate.toISOString().split('T')[0],
tanggal: currentDate.toISOString().split('T')[0] ?? '',
total_predictions: 100 + Math.floor(Math.random() * 100),
total_chicken_count: totalChickenCount + Math.floor(Math.random() * 200 - 100),
distribusi: initialWeightDistribution.map((item) => ({