Handle passed consulting sessions for admin and member

Problem: Passed consulting sessions stayed in "Dikonfirmasi" status indefinitely,
showing JOIN button to members even after session ended, with no admin action buttons.

Solution:
1. Admin UI (AdminConsulting.tsx):
   - Add isSessionPassed() helper to check if session end time has passed
   - Add "Sesi Terlewat" alert card at top with quick action buttons
   - Add "Perlu Update" stat card (orange) for passed confirmed sessions
   - Existing action buttons (Selesai/Batal) already work for confirmed sessions

2. Member UI (ConsultingHistory.tsx):
   - Move passed confirmed sessions from "Sesi Mendatang" to new "Sesi Terlewat" section
   - Remove JOIN button for passed sessions
   - Show "Menunggu konfirmasi admin" status message
   - Display with orange styling to indicate needs attention

3. Order Detail (OrderDetail.tsx):
   - Add isConsultingSessionPassed check
   - Show orange alert for passed paid sessions: "Sesi telah berakhir. Menunggu konfirmasi admin"
   - Keep green alert for upcoming paid sessions

Flow:
- Session ends → Still shows "confirmed" status
- Admin sees orange alert → Clicks Selesai or Batal
- Member sees passed session → No JOIN button → Waits for admin
- Admin updates status → Session moves to completed/cancelled

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
dwindown
2025-12-31 12:59:07 +07:00
parent 9e76d07cc2
commit 0be27ccf99
3 changed files with 111 additions and 10 deletions

View File

@@ -87,6 +87,12 @@ export function ConsultingHistory({ userId }: ConsultingHistoryProps) {
}
};
// Check if session has passed
const isSessionPassed = (session: ConsultingSession) => {
const sessionEndDateTime = new Date(`${session.session_date}T${session.end_time}`);
return new Date() > sessionEndDateTime;
};
const openReviewModal = (session: ConsultingSession) => {
const dateLabel = format(new Date(session.session_date), 'd MMMM yyyy', { locale: id });
const timeLabel = `${session.start_time.substring(0, 5)} - ${session.end_time.substring(0, 5)}`;
@@ -128,7 +134,8 @@ export function ConsultingHistory({ userId }: ConsultingHistoryProps) {
};
const doneSessions = sessions.filter(s => s.status === 'done' || s.status === 'completed');
const upcomingSessions = sessions.filter(s => s.status === 'confirmed');
const upcomingSessions = sessions.filter(s => s.status === 'confirmed' && !isSessionPassed(s));
const passedSessions = sessions.filter(s => s.status === 'confirmed' && isSessionPassed(s));
if (loading) {
return (
@@ -212,6 +219,33 @@ export function ConsultingHistory({ userId }: ConsultingHistoryProps) {
</div>
)}
{/* Passed confirmed sessions (waiting for admin action) */}
{passedSessions.length > 0 && (
<div className="space-y-2">
<h4 className="text-sm font-medium text-orange-600 dark:text-orange-400">Sesi Terlewat</h4>
{passedSessions.map((session) => (
<div key={session.id} className="flex items-center justify-between p-3 border-2 border-orange-200 bg-orange-50 dark:bg-orange-950/20">
<div className="flex items-center gap-3">
<Clock className="w-4 h-4 text-orange-600" />
<div>
<p className="font-medium">
{format(new Date(session.session_date), 'd MMM yyyy', { locale: id })}
</p>
<p className="text-sm text-muted-foreground flex items-center gap-1">
{session.start_time.substring(0, 5)} - {session.end_time.substring(0, 5)}
{session.topic_category && `${session.topic_category}`}
</p>
</div>
</div>
<div className="flex items-center gap-2">
{getStatusBadge(session.status)}
<span className="text-xs text-muted-foreground">Menunggu konfirmasi admin</span>
</div>
</div>
))}
</div>
)}
{/* Completed sessions */}
{doneSessions.length > 0 && (
<div className="space-y-2">