This commit is contained in:
chamikaJ
2025-04-17 18:28:54 +05:30
parent f583291d8a
commit 8825b0410a
2837 changed files with 241385 additions and 127578 deletions

View File

@@ -0,0 +1,109 @@
{
"log_data": [
{
"log_day": "2023-09-18",
"logs": [
{
"project_name": "Data leakage detection system",
"project_key": "DLDS",
"task_key_num": "22",
"task_name": "fgdfgdf",
"avatar_url": null,
"created_at": "2024-11-18T08:12:26.232Z",
"end_date": "2024-11-19T00:00:00.000Z",
"start_date": "2024-11-12T00:00:00.000Z",
"task_key": "GHF-2",
"time_spent": "24.000000",
"time_spent_string": "0m 24s",
"user_email": "johndoe1990@gmail.com",
"user_name": "John Doe"
}
]
},
{
"log_day": "2024-11-18",
"logs": [
{
"project_name": "Data leakage detection system",
"project_key": "DLDS",
"task_key_num": "1",
"task_name": "test task",
"avatar_url": null,
"created_at": "2024-11-18T14:04:20.811Z",
"end_date": "2024-11-19T00:00:00.000Z",
"start_date": "2024-11-12T00:00:00.000Z",
"task_key": "GFG-1",
"time_spent": "13.000000",
"time_spent_string": "0m 13s",
"user_email": "johndoe1990@gmail.com",
"user_name": "John Doe"
},
{
"project_name": "gfgdf",
"project_key": "GFG",
"task_key_num": "4",
"task_name": "fdfs",
"avatar_url": null,
"created_at": "2024-11-18T08:10:20.473Z",
"end_date": "2024-11-19T00:00:00.000Z",
"start_date": "2024-11-12T00:00:00.000Z",
"task_key": "GFG-4",
"time_spent": "74.000000",
"time_spent_string": "1m 14s",
"user_email": "johndoe1990@gmail.com",
"user_name": "John Doe"
},
{
"project_name": "gfgdf",
"project_key": "GFG",
"task_key_num": "1",
"task_name": "test task",
"avatar_url": null,
"created_at": "2024-11-18T08:10:06.902Z",
"end_date": "2024-11-19T00:00:00.000Z",
"start_date": "2024-11-12T00:00:00.000Z",
"task_key": "GFG-1",
"time_spent": "86.000000",
"time_spent_string": "1m 26s",
"user_email": "johndoe1990@gmail.com",
"user_name": "John Doe"
},
{
"project_name": "gfgdf",
"project_key": "GFG",
"task_key_num": "1",
"task_name": "test task",
"avatar_url": null,
"created_at": "2024-11-18T08:09:15.810Z",
"end_date": "2024-11-19T00:00:00.000Z",
"start_date": "2024-11-12T00:00:00.000Z",
"task_key": "GFG-1",
"time_spent": "14.000000",
"time_spent_string": "0m 14s",
"user_email": "johndoe1990@gmail.com",
"user_name": "John Doe"
}
]
},
{
"log_day": "2024-11-19",
"logs": [
{
"project_name": "gfgdf",
"project_key": "GFG",
"task_key_num": "1",
"task_name": "test task",
"avatar_url": null,
"created_at": "2024-11-19T06:42:56.726Z",
"end_date": "2024-11-19T00:00:00.000Z",
"start_date": "2024-11-12T00:00:00.000Z",
"task_key": "GFG-1",
"time_spent": "8.000000",
"time_spent_string": "0m 8s",
"user_email": "johndoe1990@gmail.com",
"user_name": "John Doe"
}
]
}
]
}

View File

@@ -0,0 +1,3 @@
.time-log-card .ant-card-body {
padding-bottom: 0 !important;
}

View File

@@ -0,0 +1,128 @@
import { Avatar, Button, Card, Divider, Drawer, Tag, Timeline, Typography } from 'antd';
import React, { useState, useEffect } from 'react';
import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { toggleTimeLogDrawer } from './timeLogSlice';
import { DownloadOutlined } from '@ant-design/icons';
import jsonData from './ProjectTimeLog.json';
import { AvatarNamesMap, durations } from '../../../shared/constants';
import './ProjectTimeLogDrawer.css';
import { useTranslation } from 'react-i18next';
import TimeWiseFilter from '@/components/reporting/time-wise-filter';
import { IProjectLogsBreakdown, ITimeLogBreakdownReq } from '@/types/reporting/reporting.types';
import { reportingTimesheetApiService } from '@/api/reporting/reporting.timesheet.api.service';
import { useAuthService } from '@/hooks/useAuth';
import logger from '@/utils/errorLogger';
const ProjectTimeLogDrawer: React.FC = () => {
const dispatch = useAppDispatch();
const { t } = useTranslation('time-report');
const currentSession = useAuthService().getCurrentSession();
const { selectedLabel, isTimeLogDrawerOpen } = useAppSelector(state => state.timeLogReducer);
const {
teams,
loadingTeams,
categories,
loadingCategories,
projects: filterProjects,
loadingProjects,
billable,
archived,
} = useAppSelector(state => state.timeReportsOverviewReducer);
const { duration, dateRange } = useAppSelector(state => state.reportingReducer);
const [projectTimeLogs, setProjectTimeLogs] = useState<IProjectLogsBreakdown[]>([]);
// Format date to desired format
const formatDate = (date: string) => {
const formattedDate = new Date(date).toLocaleDateString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric',
});
return formattedDate;
};
const handleDrawerOpen = async () => {
if (!selectedLabel?.id) return;
try {
const body: ITimeLogBreakdownReq = {
id: selectedLabel.id,
duration: duration ? duration : durations[1].key,
date_range: dateRange,
time_zone: currentSession?.timezone_name
? (currentSession?.timezone_name as string)
: (Intl.DateTimeFormat().resolvedOptions().timeZone as string),
};
const res = await reportingTimesheetApiService.getProjectTimeLogs(body);
if (res.done) {
setProjectTimeLogs(res.body || []);
}
} catch (error) {
logger.error('Error fetching project time logs:', error);
}
};
return (
<Drawer
width={736}
open={isTimeLogDrawerOpen}
onClose={() => dispatch(toggleTimeLogDrawer())}
title={
<div style={{ display: 'flex', justifyContent: 'space-between', width: '100%' }}>
<Typography.Title level={5}>{selectedLabel?.name}</Typography.Title>
<TimeWiseFilter />
</div>
}
destroyOnClose
afterOpenChange={() => {
handleDrawerOpen();
}}
>
<div style={{ textAlign: 'right', width: '100%', height: '40px' }}>
<Button size="small" icon={<DownloadOutlined />}>
{t('exportToExcel')}
</Button>
</div>
{projectTimeLogs.map(logItem => (
<div key={logItem.log_day}>
<Card
className="time-log-card"
title={
<Typography.Text
style={{ fontWeight: 500, fontSize: '16px', overflowWrap: 'break-word' }}
>
{formatDate(logItem.log_day)}
</Typography.Text>
}
>
<Timeline>
{logItem.logs.map((log, index) => (
<Timeline.Item key={index}>
<div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
<Avatar
style={{
backgroundColor: AvatarNamesMap[log.user_name.charAt(0)],
width: '26px',
height: '26px',
}}
>
{log.user_name.charAt(0).toUpperCase()}
</Avatar>
<Typography.Text>
<b>{log.user_name}</b> {t('logged')} <b>{log.time_spent_string}</b> {t('for')}{' '}
<b>{log.task_name}</b> <Tag>{log.task_key}</Tag>
</Typography.Text>
</div>
</Timeline.Item>
))}
</Timeline>
</Card>
<Divider />
</div>
))}
</Drawer>
);
};
export default ProjectTimeLogDrawer;

View File

@@ -0,0 +1,34 @@
import { IRPTTimeProject } from '@/types/reporting/reporting.types';
import { createSlice } from '@reduxjs/toolkit';
interface timeLogState {
isTimeLogDrawerOpen: boolean;
selectedLabel: IRPTTimeProject | null;
}
const initialState: timeLogState = {
isTimeLogDrawerOpen: false,
selectedLabel: null,
};
const timeLogSlice = createSlice({
name: 'timeLogReducer',
initialState,
reducers: {
toggleTimeLogDrawer: state => {
state.isTimeLogDrawerOpen
? (state.isTimeLogDrawerOpen = false)
: (state.isTimeLogDrawerOpen = true);
},
setSelectedLabel(state, action) {
state.selectedLabel = action.payload;
},
setLabelAndToggleDrawer(state, action) {
state.selectedLabel = action.payload;
state.isTimeLogDrawerOpen = true;
},
},
});
export const { toggleTimeLogDrawer, setSelectedLabel, setLabelAndToggleDrawer } = timeLogSlice.actions;
export default timeLogSlice.reducer;