A
Anonymous

Styled Card - Copy this React, Mui Component to your project

This is my attendance page code i am also rendering total times in humanize format here. So, i also wanted to show this timings into my home page dashboard so make adjustments into home page code : // ** React Imports import { Suspense, useMemo, useRef, useState } from 'react' // ** MUI imports import { Box, Stack, Typography } from '@mui/material' // ** Full Calendar Imports import { EventInput } from '@fullcalendar/core' // Ensure you're importing types from core import dayGridPlugin from '@fullcalendar/daygrid' import interactionPlugin from '@fullcalendar/interaction' import FullCalendar from '@fullcalendar/react' // Import FullCalendar from the top level library import timeGridPlugin from '@fullcalendar/timegrid' // ** Components Imports import FallbackSpinner from 'src/@core/components/spinner' // ** Hooks import useTrackingStats from 'src/@core/hooks/useTrackingStats' // ** Helper import apiHelper from 'src/@core/utils/api helper' // ** Configs import { endpointConfig } from 'src/configs/default' // ** Types import { AttendanceEvent } from 'src/@core/support/types' // ** Projection import { transformUserSelectedMonthLateMarkings } from 'src/@core/support/transform responses' const AttendanceCalendar = () => { const [events, setEvents] = useState<EventInput[]>([]) const calendarRef = useRef<any>(null) const [successfulMarkings, setSuccessfulMarkings] = useState([]) const [lateMarkings, setLateMarkings] = useState([]) const [idleMarkingsInMinutes, setIdleMarkingsInMinutes] = useState(0) const { totalHours, trackedHours, pendingHours, idleTimeMarkingHours } = useTrackingStats( successfulMarkings, lateMarkings, idleMarkingsInMinutes ) const isTrackedMonthlyTarget = useMemo(() => { return trackedHours >= totalHours }, [totalHours, trackedHours]) // Fetch attendance data for the selected month const fetchLateMarkingsData = async (year: number, month: number): Promise<AttendanceEvent[]> => { const response = await apiHelper.get(${endpointConfig.user}/late markings, { params: { year, month } }) if (response.status !== 200) { console.error('Failed to fetch attendance data:', response.data) return [] } setSuccessfulMarkings(response.data.successfulMarkings) setLateMarkings(response.data.lateMarkings) setIdleMarkingsInMinutes(response.data.idleTimeMarkings) const latemarkingsData = await transformUserSelectedMonthLateMarkings(response.data) return latemarkingsData } // Function to load events based on the current calendar view const loadEvents = async (year: number, month: number) => { const data = await fetchLateMarkingsData(year, month) setEvents(data) } // Handle calendar's view change (when the user navigates between months) const handleDatesSet = (dateInfo: any) => { const { currentDate } = dateInfo.view.getCurrentData() loadEvents(currentDate.getFullYear(), currentDate.getMonth() + 1) } // Handle event clicks to switch views const handleEventClick = (arg: any) => { const calendarApi = calendarRef.current.getApi() calendarApi.changeView('timeGridDay', arg.event.start) } return ( <Suspense fallback={<FallbackSpinner />}> <div> <Box sx={theme => ({ display: 'flex', justifyContent: 'space between', [theme.breakpoints.between('xs', 'sm')]: { flexDirection: 'column reverse' } })} > <h2>Attendance Calendar</h2> <Box sx={{ mb: 2, border: 1, p: 2 }}> <Stack sx={{ flexDirection: 'row', gap: 2 }}> <strong>Total Hours:</strong> <Typography>{totalHours}</Typography> </Stack> <Stack sx={{ flexDirection: 'row', gap: 2 }}> <strong>Tracked Hours:</strong> <Typography>{trackedHours}</Typography> </Stack> <Stack sx={{ flexDirection: 'row', gap: 2 }}> <strong>Idle Time Hours:</strong> <Typography>{idleTimeMarkingHours}</Typography> </Stack> <Stack sx={{ flexDirection: 'row', gap: 2 }}> <strong>Pending Hours:</strong>{' '} <Typography sx={theme => ({ color: isTrackedMonthlyTarget ? theme.palette.success.dark : theme.palette.error.dark })} > {pendingHours} </Typography> </Stack> </Box> </Box> <FullCalendar ref={calendarRef} // Attach ref to FullCalendar plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]} timeZone='Asia/Kolkata' initialView='dayGridMonth' events={events} eventClick={handleEventClick} datesSet={handleDatesSet} // Load events when the month changes headerToolbar={{ left: 'prev,next today', center: 'title', right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek' }} editable={false} selectable={true} /> </div> </Suspense> ) } AttendanceCalendar.acl = { action: 'read', subject: 'client page' } export default AttendanceCalendar useTrackingState hook: // ** React Imports import { useMemo } from 'react' // ** Utils Imports import { formatTrackerTimings } from '../utils/format' // ** Types Imports import type { LateSuccessfulMarkings } from '../support/types' interface AttendanceStats { totalHours: string trackedHours: string pendingHours: string idleTimeMarkingHours: string } const useTrackingStats = ( successfulMarkings: LateSuccessfulMarkings[], lateMarkings: LateSuccessfulMarkings[], idleTimeMarkings: number ): AttendanceStats => { // Check if a date is a Saturday const isSaturday = (date: string) => new Date(date).getDay() === 6 // Calculate stats const stats = useMemo(() => { // Combining both marking arrays const allMarkings = [...successfulMarkings, ...lateMarkings] // Total target hours in minutes const totalTargetMinutes = allMarkings.reduce((total, marking) => { const targetMinutes = isSaturday(marking.date) ? 240 : 480 // 4 hours or 8 hours in minutes return total + targetMinutes }, 0) // Total tracked minutes const totalTrackedMinutes = allMarkings.reduce((total, marking) => total + marking.totalTrackedTime, 0) // Calculate hours from minutes const totalHours = formatTrackerTimings(totalTargetMinutes, true) const trackedHours = formatTrackerTimings(totalTrackedMinutes, true) const pendingHours = formatTrackerTimings(Math.max(totalTargetMinutes totalTrackedMinutes, 0), true) // Ensure no negative value const idleTimeMarkingHours = formatTrackerTimings(idleTimeMarkings, true) return { totalHours, trackedHours, pendingHours, idleTimeMarkingHours } }, [successfulMarkings, lateMarkings, idleTimeMarkings]) return stats } export default useTrackingStats

Prompt

About

StyledCard - Create user dashboard cards to display monthly tracker stats from the API, built with React and MUI. Get free template!

Share

Last updated 1 month ago