daily log detail view is done
This commit is contained in:
parent
8b022bfbce
commit
98ab87fcbd
@ -1,14 +1,25 @@
|
||||
import { formatValue } from '../../lib/format';
|
||||
import { User as UserIcon, Clock, LogOut } from 'lucide-react';
|
||||
import { User as UserIcon, Clock, LogOut, FileText } from 'lucide-react';
|
||||
import { Button } from '../buttons/Button';
|
||||
import './card.css';
|
||||
|
||||
export function DailyLogCard({ row, onPunchOut }: { row: Record<string, any>; onPunchOut?: (row: any) => void }) {
|
||||
export function DailyLogCard({ row, onPunchOut, isDetailView = false }: { row: Record<string, any>; onPunchOut?: (row: any) => void; isDetailView?: boolean }) {
|
||||
const stateName = String(row.status || row.current_state_name || 'Logged');
|
||||
|
||||
// User details
|
||||
const userObj = (row.sales_officer_name || row.user_id || row.user) as Record<string, any> | null;
|
||||
const userName = formatValue(userObj?.name || row.user_name || 'Unknown User');
|
||||
const userEmail = formatValue(userObj?.email || row.performed_by_email || row.user_email || '—');
|
||||
const initials = userName !== '—' ? String(userName).substring(0, 2).toUpperCase() : 'SO';
|
||||
|
||||
// Route Details
|
||||
const routeCode = formatValue(row.route_code || row.route || '—');
|
||||
const subRoute = formatValue(row.sub_route || row.area || '—');
|
||||
|
||||
// End of Day Stats
|
||||
const prodCalls = formatValue(row.total_productive_calls || 0);
|
||||
const nonProdCalls = formatValue(row.total_non_productive_calls || 0);
|
||||
const eodNotes = formatValue(row.eod_notes_remarks || row.notes || '—');
|
||||
|
||||
// Date
|
||||
let dateStr = '—';
|
||||
@ -59,7 +70,7 @@ export function DailyLogCard({ row, onPunchOut }: { row: Record<string, any>; on
|
||||
}
|
||||
let checkOutTime = checkOutTimeRaw ? formatTimeStr(checkOutTimeRaw) : null;
|
||||
|
||||
const isPunchedIn = stateName.toLowerCase().includes('in') || stateName.toLowerCase().includes('active');
|
||||
const isPunchedIn = stateName.toLowerCase().includes('punched in') || stateName.toLowerCase().includes('active') || (stateName.toLowerCase().includes('in') && !stateName.toLowerCase().includes('out'));
|
||||
|
||||
let statusClass = 'z-card-status--neutral';
|
||||
if (isPunchedIn) statusClass = 'z-card-status--success';
|
||||
@ -69,41 +80,113 @@ export function DailyLogCard({ row, onPunchOut }: { row: Record<string, any>; on
|
||||
<div className="z-card">
|
||||
<div className="z-card-header">
|
||||
<div className="z-card-header-icon">
|
||||
<UserIcon size={16} className="text-strong" />
|
||||
<span className="text-strong">{userName}</span>
|
||||
{isDetailView ? (
|
||||
<div className="z-card-so-info" style={{ marginTop: 0 }}>
|
||||
<div className="z-card-so-avatar">
|
||||
{initials}
|
||||
</div>
|
||||
<div className="z-card-so-details">
|
||||
<p className="z-card-so-name" style={{ fontSize: '15px' }}>{userName}</p>
|
||||
{userEmail !== '—' && (
|
||||
<p className="z-card-so-email">{userEmail}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<UserIcon size={16} className="text-strong" />
|
||||
<span className="text-strong">{userName}</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<span className={`z-card-status ${statusClass}`}>
|
||||
{stateName}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="z-card-divider"></div>
|
||||
|
||||
<div className="z-card-footer" style={{ flexDirection: 'column', alignItems: 'flex-start', gap: '16px' }}>
|
||||
<div className="z-card-footer-item" style={{ width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: '4px' }}>
|
||||
<div className="z-card-footer-label" style={{ whiteSpace: 'nowrap' }}><Clock size={14} /> PUNCH-IN TIME</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '6px', whiteSpace: 'nowrap' }}>
|
||||
<span className="z-card-footer-value" style={{ display: 'flex', gap: '6px', fontSize: '13px' }}>
|
||||
<span>{dateStr}</span>
|
||||
<span>{checkInTime}</span>
|
||||
</span>
|
||||
{!isDetailView && (
|
||||
<>
|
||||
<div className="z-card-divider"></div>
|
||||
<div className="z-card-footer" style={{ flexDirection: 'column', alignItems: 'flex-start', gap: '16px' }}>
|
||||
<div className="z-card-footer-item" style={{ width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: '4px' }}>
|
||||
<div className="z-card-footer-label" style={{ whiteSpace: 'nowrap' }}><Clock size={14} /> PUNCH-IN TIME</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '6px', whiteSpace: 'nowrap' }}>
|
||||
<span className="z-card-footer-value" style={{ display: 'flex', gap: '6px', fontSize: '13px' }}>
|
||||
<span>{dateStr}</span>
|
||||
<span>{checkInTime}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{checkOutTime && (
|
||||
<div className="z-card-footer-item" style={{ width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: '4px' }}>
|
||||
<div className="z-card-footer-label" style={{ whiteSpace: 'nowrap' }}><Clock size={14} /> PUNCH-OUT TIME</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '6px', whiteSpace: 'nowrap' }}>
|
||||
<span className="z-card-footer-value" style={{ display: 'flex', gap: '6px', fontSize: '13px' }}>
|
||||
<span>{dateStr}</span>
|
||||
<span>{checkOutTime}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{checkOutTime && (
|
||||
<div className="z-card-footer-item" style={{ width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: '4px' }}>
|
||||
<div className="z-card-footer-label" style={{ whiteSpace: 'nowrap' }}><Clock size={14} /> PUNCH-OUT TIME</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '6px', whiteSpace: 'nowrap' }}>
|
||||
<span className="z-card-footer-value" style={{ display: 'flex', gap: '6px', fontSize: '13px' }}>
|
||||
<span>{dateStr}</span>
|
||||
<span>{checkOutTime}</span>
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
|
||||
{isDetailView && (
|
||||
<>
|
||||
<div className="z-card-route mt-4">
|
||||
<div>
|
||||
<p className="z-card-grid-item-label">Route Code</p>
|
||||
<p className="z-card-route-val">{routeCode}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="z-card-grid-item-label">Sub Route</p>
|
||||
<p className="z-card-route-val">{subRoute}</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="z-card-route mt-4" style={{ paddingTop: '16px', gridTemplateColumns: 'repeat(2, 1fr)' }}>
|
||||
<div>
|
||||
<p className="z-card-grid-item-label flex items-center gap-1"><Clock size={12} /> PUNCH-IN</p>
|
||||
<p className="z-card-route-val" style={{ fontSize: '13px' }}>{dateStr} {checkInTime}</p>
|
||||
</div>
|
||||
{checkOutTime && (
|
||||
<div>
|
||||
<p className="z-card-grid-item-label flex items-center gap-1"><Clock size={12} /> PUNCH-OUT</p>
|
||||
<p className="z-card-route-val" style={{ fontSize: '13px' }}>{dateStr} {checkOutTime}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!isPunchedIn && (
|
||||
<>
|
||||
<div className="mt-6 flex justify-between items-center bg-gray-50 p-4 rounded-xl border border-gray-200 shadow-sm">
|
||||
<div className="flex flex-col">
|
||||
<span className="z-card-grid-item-label" style={{ fontSize: '11px' }}>Productive</span>
|
||||
<span className="text-xl font-black text-gray-900 mt-1">{prodCalls} <span className="z-card-meta">Calls</span></span>
|
||||
</div>
|
||||
<div className="flex flex-col text-right">
|
||||
<span className="z-card-grid-item-label" style={{ fontSize: '11px' }}>Non Productive</span>
|
||||
<span className="text-xl font-black text-gray-900 mt-1">{nonProdCalls} <span className="z-card-meta">Calls</span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{eodNotes !== '—' && (
|
||||
<div className="mt-4 p-4 bg-gray-50 rounded-xl border border-gray-200">
|
||||
<div className="flex items-center gap-2 mb-2 text-gray-700">
|
||||
<FileText size={16} className="text-gray-500" />
|
||||
<span className="z-card-grid-item-label" style={{ fontSize: '12px' }}>EOD Notes</span>
|
||||
</div>
|
||||
<p className="z-card-meta-val leading-relaxed">{eodNotes}</p>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{isPunchedIn && onPunchOut && (
|
||||
<div style={{ padding: '0 6px 0px 6px' }}>
|
||||
<div style={{ padding: '16px 6px 0px 6px' }}>
|
||||
<Button
|
||||
variant="danger"
|
||||
full
|
||||
|
||||
@ -211,7 +211,7 @@
|
||||
.z-card-grid-item-label {
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
color: var(--z-text-neutral-400);
|
||||
color: var(--z-text-neutral-600);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
@ -266,7 +266,7 @@
|
||||
|
||||
.z-card-route-val {
|
||||
font-weight: 600;
|
||||
color: var(--z-text-neutral-700);
|
||||
color: var(--z-text-neutral-900);
|
||||
margin-top: 2px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ export function DailyLogDetail({ instanceId }: WiredDetailViewProps) {
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<DailyLogCard row={data} />
|
||||
<DailyLogCard row={data} isDetailView={true} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user