update sync data from site dashboard and testing closing cycles
This commit is contained in:
1 parent
36639d8c38
commit
f49e72592c
42 files changed
+1966
-688
No files matched your search
+37
-2
@@ -1,6 +1,7 @@
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useAuth } from '../context/AuthContext.tsx';
|
||||
import { useFarm } from '../context/FarmContext.tsx';
|
||||
import { api, errorMessage } from '../services/apiClient.ts';
|
||||
import type { UserStatus } from '../types/api.ts';
|
||||
import { formatDateId, resolveCycleStatus } from '../utils/format.ts';
|
||||
|
||||
@@ -22,6 +23,10 @@ type HeaderProps = {
|
||||
onToggleTimeline: () => void;
|
||||
};
|
||||
|
||||
function canMirrorSync(status?: UserStatus | string | null): boolean {
|
||||
return status === 'gm' || status === 'gm_admin';
|
||||
}
|
||||
|
||||
const Header: React.FC<HeaderProps> = ({
|
||||
onToggleSidebar,
|
||||
isTimelineVisible,
|
||||
@@ -38,12 +43,15 @@ const Header: React.FC<HeaderProps> = ({
|
||||
setSelectedSiteId,
|
||||
setSelectedKandangId,
|
||||
setSelectedCycleId,
|
||||
reload: reloadFarm,
|
||||
} = useFarm();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [gmFilter, setGmFilter] = useState<'all' | number>('all');
|
||||
const [syncing, setSyncing] = useState(false);
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const isBuh = user?.status === 'buh' || user?.status === 'bu_admin';
|
||||
const showSync = canMirrorSync(user?.status);
|
||||
|
||||
const gmOptions = useMemo(() => {
|
||||
const byId = new Map<number, string>();
|
||||
@@ -81,6 +89,19 @@ const Header: React.FC<HeaderProps> = ({
|
||||
return () => document.removeEventListener('mousedown', onClick);
|
||||
}, []);
|
||||
|
||||
const handleMirrorSync = async () => {
|
||||
setSyncing(true);
|
||||
try {
|
||||
await api.activeSites.syncAll();
|
||||
await reloadFarm();
|
||||
} catch (err) {
|
||||
// Keep sync failures visible in the browser console; UI stays quiet.
|
||||
console.error(errorMessage(err));
|
||||
} finally {
|
||||
setSyncing(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (!user) return null;
|
||||
|
||||
return (
|
||||
@@ -164,7 +185,21 @@ const Header: React.FC<HeaderProps> = ({
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center ml-auto">
|
||||
<div className="flex items-center ml-auto gap-2">
|
||||
{showSync && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => void handleMirrorSync()}
|
||||
disabled={syncing}
|
||||
title="Sinkronkan data dari site dashboard"
|
||||
className="inline-flex items-center gap-2 px-3 py-1.5 rounded-lg bg-red-600 text-white text-sm font-semibold hover:bg-red-700 disabled:opacity-60"
|
||||
>
|
||||
<i
|
||||
className={`fa-solid ${syncing ? 'fa-spinner fa-spin' : 'fa-arrows-rotate'}`}
|
||||
/>
|
||||
<span className="hidden sm:inline">{syncing ? 'Sync...' : 'Sync'}</span>
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
onClick={onToggleTimeline}
|
||||
title="Toggle Linimasa"
|
||||
@@ -175,7 +210,7 @@ const Header: React.FC<HeaderProps> = ({
|
||||
/>
|
||||
</button>
|
||||
|
||||
<div className="relative ml-4" ref={dropdownRef}>
|
||||
<div className="relative ml-2" ref={dropdownRef}>
|
||||
<button
|
||||
onClick={() => setOpen(!open)}
|
||||
className="flex items-center space-x-2 focus:outline-none"
|
||||
|
||||
Reference in new issue
Block a user