/** @odoo-module **/ import { Component, useState, onWillStart } from "@odoo/owl"; import { rpc } from "@web/core/network/rpc"; import { registry } from "@web/core/registry"; import { useService } from "@web/core/utils/hooks"; export class FusionClockDashboard extends Component { static template = "fusion_clock.Dashboard"; static props = { "*": true }; setup() { this.action = useService("action"); this.state = useState({ loading: true, error: "", role: "employee", personal: {}, team: null, }); onWillStart(async () => { await this._fetchData(); }); } async _fetchData() { this.state.loading = true; this.state.error = ""; try { const data = await rpc("/fusion_clock/dashboard_data", {}); if (data.error) { this.state.error = data.error; } else { this.state.role = data.role; this.state.personal = data.personal; this.state.team = data.team; } } catch (e) { this.state.error = "Failed to load dashboard data."; } this.state.loading = false; } // ---- display helpers ---- get greeting() { const h = new Date().getHours(); if (h < 12) return "Good morning"; if (h < 17) return "Good afternoon"; return "Good evening"; } get todayLabel() { return new Date().toLocaleDateString(undefined, { weekday: "long", month: "long", day: "numeric", }); } sourceLabel(source) { return { schedule: "Posted schedule", shift: "Recurring shift", none: "—" }[source] || "—"; } initials(name) { return (name || "") .split(" ").filter(Boolean).slice(0, 2) .map((p) => p[0].toUpperCase()).join(""); } fmtDate(s) { if (!s) return ""; const d = new Date(s.replace(" ", "T") + "Z"); return d.toLocaleDateString(undefined, { month: "short", day: "numeric" }); } fmtTime(s) { if (!s) return ""; const d = new Date(s.replace(" ", "T") + "Z"); return d.toLocaleTimeString(undefined, { hour: "numeric", minute: "2-digit" }); } // ---- actions ---- onRefresh() { return this._fetchData(); } onOpenClock() { this.action.doAction({ type: "ir.actions.act_url", url: "/my/clock", target: "self" }); } onViewTimesheets() { this.action.doAction({ type: "ir.actions.act_url", url: "/my/clock/timesheets", target: "self" }); } onViewAttendances() { // hr_attendance's action is gantt-first, and the native gantt timeline // renders collapsed until a manual resize. Land on the list instead — // the better "all attendances" destination (sort/filter/export); the // gantt is still reachable from the view switcher. this.action.doAction("hr_attendance.hr_attendance_action", { viewType: "list" }); } onViewCorrections() { this.action.doAction("fusion_clock.action_fusion_clock_correction"); } onViewActivityLogs() { this.action.doAction("fusion_clock.action_fusion_clock_activity_log"); } onViewPenalties() { this.action.doAction("fusion_clock.action_fusion_clock_penalty"); } onViewShiftPlanner() { this.action.doAction("fusion_clock.action_fusion_clock_shift_planner"); } onViewBiweekly() { this.action.doAction("fusion_clock.action_fusion_clock_period_picker"); } onViewReports() { this.action.doAction("fusion_clock.action_fusion_clock_report"); } } registry.category("actions").add("fusion_clock.Dashboard", FusionClockDashboard);