before resize

This commit is contained in:
Flatlogic Bot 2026-02-17 22:36:06 +00:00
parent 40b50cdd6c
commit deb8071e36
15 changed files with 329 additions and 220 deletions

View File

@ -445,7 +445,7 @@ module.exports = class Time_off_requestsDBApi {
{
model: db.users,
as: 'requester',
required: false,
required: !!filter.requester,
where: filter.requester ? {
[Op.or]: [
{ id: { [Op.in]: filter.requester.split('|').map(term => Utils.uuid(term)) } },
@ -454,6 +454,11 @@ module.exports = class Time_off_requestsDBApi {
[Op.or]: filter.requester.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
}
},
{
lastName: {
[Op.or]: filter.requester.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
}
},
]
} : undefined,
@ -462,7 +467,7 @@ module.exports = class Time_off_requestsDBApi {
{
model: db.users,
as: 'approver',
required: false,
required: !!filter.approver,
where: filter.approver ? {
[Op.or]: [
{ id: { [Op.in]: filter.approver.split('|').map(term => Utils.uuid(term)) } },
@ -471,6 +476,11 @@ module.exports = class Time_off_requestsDBApi {
[Op.or]: filter.approver.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
}
},
{
lastName: {
[Op.or]: filter.approver.split('|').map(term => ({ [Op.iLike]: `%${term}%` }))
}
},
]
} : undefined,
@ -533,7 +543,8 @@ module.exports = class Time_off_requestsDBApi {
if (filter.starts_atRange) {
const [start, end] = filter.starts_atRange;
const range = Array.isArray(filter.starts_atRange) ? filter.starts_atRange : [filter.starts_atRange];
const [start, end] = range;
if (start !== undefined && start !== null && start !== '') {
where = {
@ -557,7 +568,8 @@ module.exports = class Time_off_requestsDBApi {
}
if (filter.ends_atRange) {
const [start, end] = filter.ends_atRange;
const range = Array.isArray(filter.ends_atRange) ? filter.ends_atRange : [filter.ends_atRange];
const [start, end] = range;
if (start !== undefined && start !== null && start !== '') {
where = {
@ -581,7 +593,8 @@ module.exports = class Time_off_requestsDBApi {
}
if (filter.hoursRange) {
const [start, end] = filter.hoursRange;
const range = Array.isArray(filter.hoursRange) ? filter.hoursRange : [filter.hoursRange];
const [start, end] = range;
if (start !== undefined && start !== null && start !== '') {
where = {
@ -605,7 +618,8 @@ module.exports = class Time_off_requestsDBApi {
}
if (filter.daysRange) {
const [start, end] = filter.daysRange;
const range = Array.isArray(filter.daysRange) ? filter.daysRange : [filter.daysRange];
const [start, end] = range;
if (start !== undefined && start !== null && start !== '') {
where = {
@ -629,7 +643,8 @@ module.exports = class Time_off_requestsDBApi {
}
if (filter.submitted_atRange) {
const [start, end] = filter.submitted_atRange;
const range = Array.isArray(filter.submitted_atRange) ? filter.submitted_atRange : [filter.submitted_atRange];
const [start, end] = range;
if (start !== undefined && start !== null && start !== '') {
where = {
@ -653,7 +668,8 @@ module.exports = class Time_off_requestsDBApi {
}
if (filter.decided_atRange) {
const [start, end] = filter.decided_atRange;
const range = Array.isArray(filter.decided_atRange) ? filter.decided_atRange : [filter.decided_atRange];
const [start, end] = range;
if (start !== undefined && start !== null && start !== '') {
where = {
@ -729,7 +745,8 @@ module.exports = class Time_off_requestsDBApi {
if (filter.createdAtRange) {
const [start, end] = filter.createdAtRange;
const range = Array.isArray(filter.createdAtRange) ? filter.createdAtRange : [filter.createdAtRange];
const [start, end] = range;
if (start !== undefined && start !== null && start !== '') {
where = {
@ -828,4 +845,4 @@ module.exports = class Time_off_requestsDBApi {
}
};
};

View File

@ -64,8 +64,8 @@ module.exports = class Time_off_requestsService {
},
);
// Create calendar event if approved
if (createdRequest.status === 'approved') {
// Create calendar event if approved or pending_approval
if (['approved', 'pending_approval'].includes(createdRequest.status)) {
await Office_calendar_eventsDBApi.create({
event_type: 'time_off',
title: `PTO - ${requester?.firstName || ''} ${requester?.lastName || ''}`,
@ -220,8 +220,12 @@ module.exports = class Time_off_requestsService {
},
);
// Create calendar event if status changed to approved
if (newStatus === 'approved' && oldStatus !== 'approved') {
// Create/Update/Delete calendar event based on status
const visibleStatuses = ['approved', 'pending_approval'];
const isVisibleNow = visibleStatuses.includes(newStatus);
const wasVisibleBefore = visibleStatuses.includes(oldStatus);
if (isVisibleNow && !wasVisibleBefore) {
const requester = await db.users.findByPk(updatedTime_off_requests.requesterId, { transaction });
await Office_calendar_eventsDBApi.create({
event_type: 'time_off',
@ -232,21 +236,23 @@ module.exports = class Time_off_requestsService {
time_off_request: updatedTime_off_requests.id,
is_all_day: true
}, { currentUser, transaction });
} else if (newStatus !== 'approved' && oldStatus === 'approved') {
// Delete calendar event if no longer approved
} else if (!isVisibleNow && wasVisibleBefore) {
// Delete calendar event if no longer visible
await db.office_calendar_events.destroy({
where: { time_off_requestId: id },
transaction
});
} else if (newStatus === 'approved' && (data.starts_at || data.ends_at)) {
} else if (isVisibleNow && wasVisibleBefore) {
// Update calendar event if dates changed
await db.office_calendar_events.update({
starts_at: updatedTime_off_requests.starts_at,
ends_at: updatedTime_off_requests.ends_at
}, {
where: { time_off_requestId: id },
transaction
});
if (data.starts_at || data.ends_at) {
await db.office_calendar_events.update({
starts_at: updatedTime_off_requests.starts_at,
ends_at: updatedTime_off_requests.ends_at
}, {
where: { time_off_requestId: id },
transaction
});
}
}
// Handle cancellation: dismiss associated approval tasks

View File

@ -25,6 +25,7 @@ type TEvent = {
event_type?: string;
user?: any;
holiday?: any;
time_off_request?: any;
};
type Props = {
@ -147,8 +148,12 @@ const BigCalendar = ({
const color = 'white';
if (entityName === 'office_calendar_events') {
if (event.event_type === 'time_off' && event.user) {
backgroundColor = stringToColor(event.user.id);
if (event.event_type === 'time_off') {
if (event.time_off_request?.status === 'approved') {
backgroundColor = '#3b82f6'; // Blue
} else {
backgroundColor = '#eab308'; // Yellow
}
} else if (event.event_type === 'holiday') {
backgroundColor = '#f0ad4e';
} else {
@ -230,4 +235,4 @@ const MyCustomEvent = (
);
};
export default BigCalendar;
export default BigCalendar;

View File

@ -14,9 +14,19 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions";
import { leaveTypeLabels } from '../Time_off_requests/configureTime_off_requestsCols';
type Params = (id: string) => void;
const getUserLabel = (user: any) => {
if (!user) return '';
if (user.label) return user.label;
if (user.firstName || user.lastName) {
return `${user.firstName || ''} ${user.lastName || ''}`.trim();
}
return user.id || '';
}
export const loadColumns = async (
onDelete: Params,
entityName: string,
@ -45,11 +55,15 @@ export const loadColumns = async (
field: 'user',
headerName: 'User',
flex: 1,
minWidth: 120,
minWidth: 150,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
renderCell: (params: GridValueGetterParams) => (
<span>
{getUserLabel(params?.row?.user)}
</span>
),
editable: hasUpdatePermission,
@ -65,9 +79,9 @@ export const loadColumns = async (
{
field: 'source_request',
headerName: 'SourceRequest',
headerName: 'Source Request',
flex: 1,
minWidth: 120,
minWidth: 150,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
@ -87,7 +101,7 @@ export const loadColumns = async (
{
field: 'entry_type',
headerName: 'EntryType',
headerName: 'Entry Type',
flex: 1,
minWidth: 120,
filterable: false,
@ -102,13 +116,17 @@ export const loadColumns = async (
{
field: 'leave_bucket',
headerName: 'LeaveBucket',
headerName: 'Leave Bucket',
flex: 1,
minWidth: 120,
minWidth: 150,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
renderCell: (params: GridValueGetterParams) => (
<span>
{leaveTypeLabels[params.value] || params.value}
</span>
),
editable: hasUpdatePermission,
@ -117,7 +135,7 @@ export const loadColumns = async (
{
field: 'effective_at',
headerName: 'EffectiveAt',
headerName: 'Effective At',
flex: 1,
minWidth: 120,
filterable: false,
@ -135,7 +153,7 @@ export const loadColumns = async (
{
field: 'calendar_year',
headerName: 'CalendarYear',
headerName: 'Calendar Year',
flex: 1,
minWidth: 120,
filterable: false,
@ -151,7 +169,7 @@ export const loadColumns = async (
{
field: 'amount_hours',
headerName: 'AmountHours',
headerName: 'Amount Hours',
flex: 1,
minWidth: 120,
filterable: false,
@ -167,7 +185,7 @@ export const loadColumns = async (
{
field: 'amount_days',
headerName: 'AmountDays',
headerName: 'Amount Days',
flex: 1,
minWidth: 120,
filterable: false,
@ -183,7 +201,7 @@ export const loadColumns = async (
{
field: 'counts_against_balance',
headerName: 'CountsAgainstBalance',
headerName: 'Counts Against Balance',
flex: 1,
minWidth: 120,
filterable: false,
@ -199,7 +217,7 @@ export const loadColumns = async (
{
field: 'posting_status',
headerName: 'PostingStatus',
headerName: 'Posting Status',
flex: 1,
minWidth: 120,
filterable: false,
@ -229,13 +247,17 @@ export const loadColumns = async (
{
field: 'entered_by',
headerName: 'EnteredBy',
headerName: 'Entered By',
flex: 1,
minWidth: 120,
minWidth: 150,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
renderCell: (params: GridValueGetterParams) => (
<span>
{getUserLabel(params?.row?.entered_by)}
</span>
),
editable: hasUpdatePermission,
@ -251,7 +273,7 @@ export const loadColumns = async (
{
field: 'entered_at',
headerName: 'EnteredAt',
headerName: 'Entered At',
flex: 1,
minWidth: 120,
filterable: false,
@ -291,4 +313,4 @@ export const loadColumns = async (
},
},
];
};
};

View File

@ -3,7 +3,7 @@ import axios from 'axios';
import moment from 'moment';
import CardBox from './CardBox';
import BaseIcon from './BaseIcon';
import { mdiArrowLeft, mdiArrowRight, mdiCalendarCheck, mdiAlertCircle, mdiDoctor } from '@mdi/js';
import { mdiArrowLeft, mdiArrowRight, mdiCalendarCheck, mdiAlertCircle, mdiDoctor, mdiClockOutline } from '@mdi/js';
interface TimeOffRequest {
id: string;
@ -49,10 +49,11 @@ export default function StaffOffList() {
// Filter client-side for status/type criteria
const filtered = response.data.rows.filter((r: any) => {
const isApproved = r.status === 'approved';
const isPending = r.status === 'pending_approval';
const isSpecialType = ['unplanned_pto', 'medical_leave'].includes(r.leave_type);
// Include if approved OR (unplanned/medical and not rejected/cancelled)
// Include if approved OR pending OR (unplanned/medical and not rejected/cancelled)
const isActive = !['rejected', 'cancelled'].includes(r.status);
return (isApproved || (isSpecialType && isActive));
return (isApproved || isPending || (isSpecialType && isActive));
});
setRequests(filtered);
@ -70,16 +71,18 @@ export default function StaffOffList() {
const prevWeek = () => setWeekStart(weekStart.clone().subtract(1, 'weeks'));
const nextWeek = () => setWeekStart(weekStart.clone().add(1, 'weeks'));
const getIcon = (type: string) => {
switch (type) {
const getIcon = (r: TimeOffRequest) => {
if (r.status === 'pending_approval') return mdiClockOutline;
switch (r.leave_type) {
case 'medical_leave': return mdiDoctor;
case 'unplanned_pto': return mdiAlertCircle;
default: return mdiCalendarCheck;
}
};
const getColor = (type: string) => {
switch (type) {
const getColor = (r: TimeOffRequest) => {
if (r.status === 'pending_approval') return 'text-yellow-500';
switch (r.leave_type) {
case 'medical_leave': return 'text-red-500';
case 'unplanned_pto': return 'text-orange-500';
default: return 'text-green-500';
@ -117,9 +120,9 @@ export default function StaffOffList() {
</div>
<div>
<div className="font-medium">{r.requester?.firstName} {r.requester?.lastName}</div>
<div className={`text-xs flex items-center ${getColor(r.leave_type)}`}>
<BaseIcon path={getIcon(r.leave_type)} size={14} className="mr-1"/>
<span className="capitalize">{r.leave_type.replace('_', ' ')}</span>
<div className={`text-xs flex items-center ${getColor(r)}`}>
<BaseIcon path={getIcon(r)} size={14} className="mr-1"/>
<span className="capitalize">{r.leave_type.replace('_', ' ')} {r.status === 'pending_approval' ? '(Pending)' : ''}</span>
</div>
</div>
</div>

View File

@ -15,7 +15,7 @@ import {
import { Drawer, Box, Typography, IconButton } from '@mui/material';
import { mdiClose } from '@mdi/js';
import BaseIcon from '../BaseIcon';
import {loadColumns} from "./configureTime_off_requestsCols";
import {loadColumns, leaveTypeLabels} from "./configureTime_off_requestsCols";
import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles";
@ -231,12 +231,10 @@ const TableSampleTime_off_requests = ({ filterItems, setFilterItems, filters, sh
);
if (isRangeFilter) {
const from = item.fields.filterValueFrom;
const to = item.fields.filterValueTo;
if (from) {
const from = item.fields.filterValueFrom || "";
const to = item.fields.filterValueTo || "";
if (from || to) {
request += `${item.fields.selectedField}Range=${from}&`;
}
if (to) {
request += `${item.fields.selectedField}Range=${to}&`;
}
} else {
@ -494,8 +492,8 @@ const TableSampleTime_off_requests = ({ filterItems, setFilterItems, filters, sh
>
<option value="">Select Value</option>
{selectedFilter?.options?.map((option) => (
<option key={option} value={option}>
{option}
<option key={typeof option === 'string' ? option : option.value} value={typeof option === 'string' ? option : option.value}>
{typeof option === 'string' ? option : option.label}
</option>
))}
</Field>
@ -628,7 +626,7 @@ const TableSampleTime_off_requests = ({ filterItems, setFilterItems, filters, sh
<div className="space-y-2">
<p><strong>Requester:</strong> {getUserLabel(selectedItem.requester)}</p>
<p><strong>Approver:</strong> {getUserLabel(selectedItem.approver)}</p>
<p><strong>Type:</strong> {selectedItem.leave_type}</p>
<p><strong>Type:</strong> {leaveTypeLabels[selectedItem.leave_type] || selectedItem.leave_type}</p>
<p><strong>Kind:</strong> {selectedItem.request_kind}</p>
<p><strong>Start:</strong> {moment(selectedItem.starts_at).format('YYYY-MM-DD HH:mm')}</p>
<p><strong>Finish:</strong> {moment(selectedItem.ends_at).format('YYYY-MM-DD HH:mm')}</p>
@ -679,4 +677,4 @@ const TableSampleTime_off_requests = ({ filterItems, setFilterItems, filters, sh
)
}
export default TableSampleTime_off_requests
export default TableSampleTime_off_requests;

View File

@ -18,6 +18,14 @@ const getUserLabel = (user: any) => {
return user.id || '';
}
export const leaveTypeLabels = {
regular_pto: 'PTO Planned',
medical_leave: 'Medical',
unplanned_pto: 'PTO Unplanned',
bereavement: 'Bereavement',
time_in_lieu: 'Time in Lieu'
};
export const loadColumns = async (
onDelete: Params,
entityName: string,
@ -108,7 +116,11 @@ export const loadColumns = async (
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
renderCell: (params: GridValueGetterParams) => (
<span>
{leaveTypeLabels[params.value] || params.value}
</span>
),
editable: hasUpdatePermission,

View File

@ -17,6 +17,15 @@ import {hasPermission} from "../../helpers/userPermissions";
type Params = (id: string) => void;
const getUserLabel = (user: any) => {
if (!user) return '';
if (user.label) return user.label;
if (user.firstName || user.lastName) {
return `${user.firstName || ''} ${user.lastName || ''}`.trim();
}
return user.id || '';
}
export const loadColumns = async (
onDelete: Params,
entityName: string,
@ -45,11 +54,15 @@ export const loadColumns = async (
field: 'user',
headerName: 'User',
flex: 1,
minWidth: 120,
minWidth: 150,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
renderCell: (params: GridValueGetterParams) => (
<span>
{getUserLabel(params?.row?.user)}
</span>
),
editable: hasUpdatePermission,
@ -65,7 +78,7 @@ export const loadColumns = async (
{
field: 'calendar_year',
headerName: 'CalendarYear',
headerName: 'Calendar Year',
flex: 1,
minWidth: 120,
filterable: false,
@ -81,7 +94,7 @@ export const loadColumns = async (
{
field: 'pto_pending_days',
headerName: 'PTOPendingDays',
headerName: 'PTO Pending',
flex: 1,
minWidth: 120,
filterable: false,
@ -97,7 +110,7 @@ export const loadColumns = async (
{
field: 'pto_scheduled_days',
headerName: 'PTOScheduledDays',
headerName: 'PTO Scheduled',
flex: 1,
minWidth: 120,
filterable: false,
@ -113,7 +126,7 @@ export const loadColumns = async (
{
field: 'pto_taken_days',
headerName: 'PTOTakenDays',
headerName: 'PTO Taken',
flex: 1,
minWidth: 120,
filterable: false,
@ -129,7 +142,7 @@ export const loadColumns = async (
{
field: 'pto_available_days',
headerName: 'PTOAvailableDays',
headerName: 'PTO Available',
flex: 1,
minWidth: 120,
filterable: false,
@ -145,7 +158,7 @@ export const loadColumns = async (
{
field: 'medical_taken_days',
headerName: 'MedicalTakenDays',
headerName: 'Medical Taken',
flex: 1,
minWidth: 120,
filterable: false,
@ -161,7 +174,7 @@ export const loadColumns = async (
{
field: 'bereavement_taken_days',
headerName: 'BereavementTakenDays',
headerName: 'Bereavement Taken',
flex: 1,
minWidth: 120,
filterable: false,
@ -177,7 +190,7 @@ export const loadColumns = async (
{
field: 'time_in_lieu_available_days',
headerName: 'TimeInLieuAvailableDays',
headerName: 'Time In Lieu Available',
flex: 1,
minWidth: 120,
filterable: false,
@ -193,7 +206,7 @@ export const loadColumns = async (
{
field: 'vacation_pay_paid_amount',
headerName: 'VacationPayPaidAmount',
headerName: 'Vacation Pay Paid',
flex: 1,
minWidth: 120,
filterable: false,
@ -255,4 +268,4 @@ export const loadColumns = async (
},
},
];
};
};

View File

@ -19,6 +19,7 @@ import BaseDivider from "../../components/BaseDivider";
import {mdiChartTimelineVariant} from "@mdi/js";
import {SwitchField} from "../../components/SwitchField";
import FormField from "../../components/FormField";
import { leaveTypeLabels } from '../../components/Time_off_requests/configureTime_off_requestsCols';
const Pto_journal_entriesView = () => {
@ -26,6 +27,14 @@ const Pto_journal_entriesView = () => {
const dispatch = useAppDispatch()
const { pto_journal_entries } = useAppSelector((state) => state.pto_journal_entries)
const getUserLabel = (user: any) => {
if (!user) return '';
if (user.label) return user.label;
if (user.firstName || user.lastName) {
return `${user.firstName || ''} ${user.lastName || ''}`.trim();
}
return user.id || '';
}
const { id } = router.query;
@ -42,10 +51,10 @@ const Pto_journal_entriesView = () => {
return (
<>
<Head>
<title>{getPageTitle('View pto_journal_entries')}</title>
<title>{getPageTitle('View Time Off Entry')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View pto_journal_entries')} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'View Time Off Entry'} main>
<BaseButton
color='info'
label='Edit'
@ -79,7 +88,7 @@ const Pto_journal_entriesView = () => {
<p className={'block font-bold mb-2'}>User</p>
<p>{pto_journal_entries?.user?.firstName ?? 'No data'}</p>
<p>{getUserLabel(pto_journal_entries?.user) || 'No data'}</p>
@ -132,7 +141,7 @@ const Pto_journal_entriesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>SourceRequest</p>
<p className={'block font-bold mb-2'}>Source Request</p>
@ -183,7 +192,7 @@ const Pto_journal_entriesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>EntryType</p>
<p className={'block font-bold mb-2'}>Entry Type</p>
<p>{pto_journal_entries?.entry_type ?? 'No data'}</p>
</div>
@ -215,8 +224,8 @@ const Pto_journal_entriesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>LeaveBucket</p>
<p>{pto_journal_entries?.leave_bucket ?? 'No data'}</p>
<p className={'block font-bold mb-2'}>Leave Bucket</p>
<p>{leaveTypeLabels[pto_journal_entries?.leave_bucket] || pto_journal_entries?.leave_bucket || 'No data'}</p>
</div>
@ -242,7 +251,7 @@ const Pto_journal_entriesView = () => {
<FormField label='EffectiveAt'>
<FormField label='Effective At'>
{pto_journal_entries.effective_at ? <DatePicker
dateFormat="yyyy-MM-dd hh:mm"
showTimeSelect
@ -252,7 +261,7 @@ const Pto_journal_entriesView = () => {
) : null
}
disabled
/> : <p>No EffectiveAt</p>}
/> : <p>No Effective At</p>}
</FormField>
@ -279,7 +288,7 @@ const Pto_journal_entriesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>CalendarYear</p>
<p className={'block font-bold mb-2'}>Calendar Year</p>
<p>{pto_journal_entries?.calendar_year || 'No data'}</p>
</div>
@ -311,7 +320,7 @@ const Pto_journal_entriesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>AmountHours</p>
<p className={'block font-bold mb-2'}>Amount Hours</p>
<p>{pto_journal_entries?.amount_hours || 'No data'}</p>
</div>
@ -343,7 +352,7 @@ const Pto_journal_entriesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>AmountDays</p>
<p className={'block font-bold mb-2'}>Amount Days</p>
<p>{pto_journal_entries?.amount_days || 'No data'}</p>
</div>
@ -384,7 +393,7 @@ const Pto_journal_entriesView = () => {
<FormField label='CountsAgainstBalance'>
<FormField label='Counts Against Balance'>
<SwitchField
field={{name: 'counts_against_balance', value: pto_journal_entries?.counts_against_balance}}
form={{setFieldValue: () => null}}
@ -418,7 +427,7 @@ const Pto_journal_entriesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>PostingStatus</p>
<p className={'block font-bold mb-2'}>Posting Status</p>
<p>{pto_journal_entries?.posting_status ?? 'No data'}</p>
</div>
@ -437,7 +446,7 @@ const Pto_journal_entriesView = () => {
<FormField label='Multi Text' hasTextareaHeight>
<FormField label='Memo' hasTextareaHeight>
<textarea className={'w-full'} disabled value={pto_journal_entries?.memo} />
</FormField>
@ -486,10 +495,10 @@ const Pto_journal_entriesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>EnteredBy</p>
<p className={'block font-bold mb-2'}>Entered By</p>
<p>{pto_journal_entries?.entered_by?.firstName ?? 'No data'}</p>
<p>{getUserLabel(pto_journal_entries?.entered_by) || 'No data'}</p>
@ -532,7 +541,7 @@ const Pto_journal_entriesView = () => {
<FormField label='EnteredAt'>
<FormField label='Entered At'>
{pto_journal_entries.entered_at ? <DatePicker
dateFormat="yyyy-MM-dd hh:mm"
showTimeSelect
@ -542,7 +551,7 @@ const Pto_journal_entriesView = () => {
) : null
}
disabled
/> : <p>No EnteredAt</p>}
/> : <p>No Entered At</p>}
</FormField>

View File

@ -50,7 +50,13 @@ const Time_off_requestsTablesPage = () => {
{label: 'Type', title: 'leave_type', type: 'enum', options: ['regular_pto','unplanned_pto','medical_leave','bereavement','time_in_lieu']},{label: 'Request Kind', title: 'request_kind', type: 'enum', options: ['take_time_off','add_time_credit','manual_adjustment']},{label: 'Status', title: 'status', type: 'enum', options: ['draft','pending_approval','approved','rejected','cancelled']},
{label: 'Type', title: 'leave_type', type: 'enum', options: [
{ value: 'regular_pto', label: 'PTO Planned' },
{ value: 'medical_leave', label: 'Medical' },
{ value: 'unplanned_pto', label: 'PTO Unplanned' },
{ value: 'bereavement', label: 'Bereavement' },
{ value: 'time_in_lieu', label: 'Time in Lieu' }
]},{label: 'Request Kind', title: 'request_kind', type: 'enum', options: ['take_time_off','add_time_credit','manual_adjustment']},{label: 'Status', title: 'status', type: 'enum', options: ['draft','pending_approval','approved','rejected','cancelled']},
]);
const hasCreatePermission = currentUser && hasPermission(currentUser, 'CREATE_TIME_OFF_REQUESTS');
@ -176,4 +182,4 @@ Time_off_requestsTablesPage.getLayout = function getLayout(page: ReactElement) {
)
}
export default Time_off_requestsTablesPage
export default Time_off_requestsTablesPage;

View File

@ -19,6 +19,7 @@ import BaseDivider from "../../components/BaseDivider";
import {mdiChartTimelineVariant} from "@mdi/js";
import {SwitchField} from "../../components/SwitchField";
import FormField from "../../components/FormField";
import { leaveTypeLabels } from '../../components/Time_off_requests/configureTime_off_requestsCols';
const Time_off_requestsView = () => {
@ -26,6 +27,14 @@ const Time_off_requestsView = () => {
const dispatch = useAppDispatch()
const { time_off_requests } = useAppSelector((state) => state.time_off_requests)
const getUserLabel = (user: any) => {
if (!user) return '';
if (user.label) return user.label;
if (user.firstName || user.lastName) {
return `${user.firstName || ''} ${user.lastName || ''}`.trim();
}
return user.id || '';
}
const { id } = router.query;
@ -42,10 +51,10 @@ const Time_off_requestsView = () => {
return (
<>
<Head>
<title>{getPageTitle('View time_off_requests')}</title>
<title>{getPageTitle('View Time Off Request')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View time_off_requests')} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'View Time Off Request'} main>
<BaseButton
color='info'
label='Edit'
@ -79,7 +88,7 @@ const Time_off_requestsView = () => {
<p className={'block font-bold mb-2'}>Requester</p>
<p>{time_off_requests?.requester?.firstName ?? 'No data'}</p>
<p>{getUserLabel(time_off_requests?.requester) || 'No data'}</p>
@ -135,7 +144,7 @@ const Time_off_requestsView = () => {
<p className={'block font-bold mb-2'}>Approver</p>
<p>{time_off_requests?.approver?.firstName ?? 'No data'}</p>
<p>{getUserLabel(time_off_requests?.approver) || 'No data'}</p>
@ -183,8 +192,8 @@ const Time_off_requestsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>LeaveType</p>
<p>{time_off_requests?.leave_type ?? 'No data'}</p>
<p className={'block font-bold mb-2'}>Type</p>
<p>{leaveTypeLabels[time_off_requests?.leave_type] || time_off_requests?.leave_type || 'No data'}</p>
</div>
@ -215,7 +224,7 @@ const Time_off_requestsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>RequestKind</p>
<p className={'block font-bold mb-2'}>Kind</p>
<p>{time_off_requests?.request_kind ?? 'No data'}</p>
</div>
@ -242,7 +251,7 @@ const Time_off_requestsView = () => {
<FormField label='StartsAt'>
<FormField label='Start'>
{time_off_requests.starts_at ? <DatePicker
dateFormat="yyyy-MM-dd hh:mm"
showTimeSelect
@ -252,7 +261,7 @@ const Time_off_requestsView = () => {
) : null
}
disabled
/> : <p>No StartsAt</p>}
/> : <p>No Start</p>}
</FormField>
@ -282,7 +291,7 @@ const Time_off_requestsView = () => {
<FormField label='EndsAt'>
<FormField label='Finish'>
{time_off_requests.ends_at ? <DatePicker
dateFormat="yyyy-MM-dd hh:mm"
showTimeSelect
@ -292,7 +301,7 @@ const Time_off_requestsView = () => {
) : null
}
disabled
/> : <p>No EndsAt</p>}
/> : <p>No Finish</p>}
</FormField>
@ -424,7 +433,7 @@ const Time_off_requestsView = () => {
<FormField label='RequiresApproval'>
<FormField label='Requires Approval'>
<SwitchField
field={{name: 'requires_approval', value: time_off_requests?.requires_approval}}
form={{setFieldValue: () => null}}
@ -453,7 +462,7 @@ const Time_off_requestsView = () => {
<FormField label='SubmittedAt'>
<FormField label='Submitted At'>
{time_off_requests.submitted_at ? <DatePicker
dateFormat="yyyy-MM-dd hh:mm"
showTimeSelect
@ -463,7 +472,7 @@ const Time_off_requestsView = () => {
) : null
}
disabled
/> : <p>No SubmittedAt</p>}
/> : <p>No Submitted At</p>}
</FormField>
@ -493,7 +502,7 @@ const Time_off_requestsView = () => {
<FormField label='DecidedAt'>
<FormField label='Decided At'>
{time_off_requests.decided_at ? <DatePicker
dateFormat="yyyy-MM-dd hh:mm"
showTimeSelect
@ -503,7 +512,7 @@ const Time_off_requestsView = () => {
) : null
}
disabled
/> : <p>No DecidedAt</p>}
/> : <p>No Decided At</p>}
</FormField>
@ -525,7 +534,7 @@ const Time_off_requestsView = () => {
<FormField label='Multi Text' hasTextareaHeight>
<FormField label='Reason' hasTextareaHeight>
<textarea className={'w-full'} disabled value={time_off_requests?.reason} />
</FormField>
@ -556,7 +565,7 @@ const Time_off_requestsView = () => {
<FormField label='Multi Text' hasTextareaHeight>
<FormField label='Manager Note' hasTextareaHeight>
<textarea className={'w-full'} disabled value={time_off_requests?.manager_note} />
</FormField>
@ -627,7 +636,7 @@ const Time_off_requestsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>ExternalReference</p>
<p className={'block font-bold mb-2'}>External Reference</p>
<p>{time_off_requests?.external_reference}</p>
</div>
@ -665,7 +674,7 @@ const Time_off_requestsView = () => {
<>
<p className={'block font-bold mb-2'}>Pto_journal_entries SourceRequest</p>
<p className={'block font-bold mb-2'}>Time Off History</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -680,35 +689,35 @@ const Time_off_requestsView = () => {
<th>EntryType</th>
<th>Entry Type</th>
<th>LeaveBucket</th>
<th>Leave Bucket</th>
<th>EffectiveAt</th>
<th>Effective At</th>
<th>CalendarYear</th>
<th>Calendar Year</th>
<th>AmountHours</th>
<th>Amount Hours</th>
<th>AmountDays</th>
<th>Amount Days</th>
<th>CountsAgainstBalance</th>
<th>Counts Against Balance</th>
<th>PostingStatus</th>
<th>Posting Status</th>
@ -718,7 +727,7 @@ const Time_off_requestsView = () => {
<th>EnteredAt</th>
<th>Entered At</th>
</tr>
@ -740,7 +749,7 @@ const Time_off_requestsView = () => {
<td data-label="leave_bucket">
{ item.leave_bucket }
{ leaveTypeLabels[item.leave_bucket] || item.leave_bucket }
</td>
@ -806,7 +815,7 @@ const Time_off_requestsView = () => {
<>
<p className={'block font-bold mb-2'}>Office_calendar_events TimeOffRequest</p>
<p className={'block font-bold mb-2'}>Calendar Events</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -817,7 +826,7 @@ const Time_off_requestsView = () => {
<tr>
<th>EventType</th>
<th>Event Type</th>
@ -831,15 +840,15 @@ const Time_off_requestsView = () => {
<th>StartsAt</th>
<th>Start</th>
<th>EndsAt</th>
<th>Finish</th>
<th>IsAllDay</th>
<th>All Day</th>
@ -906,7 +915,7 @@ const Time_off_requestsView = () => {
<>
<p className={'block font-bold mb-2'}>Approval_tasks TimeOffRequest</p>
<p className={'block font-bold mb-2'}>Approval Tasks</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -925,11 +934,11 @@ const Time_off_requestsView = () => {
<th>DueAt</th>
<th>Due At</th>
<th>CompletedAt</th>
<th>Completed At</th>

View File

@ -177,13 +177,13 @@ const EditUsersPage = () => {
</FormField>
{values.leave_policy_type === 'pto' && (
<FormField label="Paid PTO Per Year">
<Field name="paid_pto_per_year" placeholder="Paid PTO Per Year" type="number" />
<FormField label="PTO Planned Per Year">
<Field name="paid_pto_per_year" placeholder="PTO Planned Per Year" type="number" />
</FormField>
)}
<FormField label="Medical Leave Per Year">
<Field name="medical_leave_per_year" placeholder="Medical Leave Per Year" type="number" />
<FormField label="Medical Per Year">
<Field name="medical_leave_per_year" placeholder="Medical Per Year" type="number" />
</FormField>
<FormField label="Bereavement Per Year">

View File

@ -132,13 +132,13 @@ const UsersNew = () => {
</FormField>
{values.leave_policy_type === 'pto' && (
<FormField label="Paid PTO Per Year">
<Field name="paid_pto_per_year" placeholder="Paid PTO Per Year" type="number" />
<FormField label="PTO Planned Per Year">
<Field name="paid_pto_per_year" placeholder="PTO Planned Per Year" type="number" />
</FormField>
)}
<FormField label="Medical Leave Per Year">
<Field name="medical_leave_per_year" placeholder="Medical Leave Per Year" type="number" />
<FormField label="Medical Per Year">
<Field name="medical_leave_per_year" placeholder="Medical Per Year" type="number" />
</FormField>
<FormField label="Bereavement Per Year">

View File

@ -20,6 +20,7 @@ import {mdiChartTimelineVariant} from "@mdi/js";
import {SwitchField} from "../../components/SwitchField";
import FormField from "../../components/FormField";
import LoginHistoryTable from "../../components/Users/LoginHistoryTable";
import { leaveTypeLabels } from '../../components/Time_off_requests/configureTime_off_requestsCols';
const UsersView = () => {
@ -410,7 +411,7 @@ const UsersView = () => {
<>
<p className={'block font-bold mb-2'}>Time_off_requests Requester</p>
<p className={'block font-bold mb-2'}>Time Off Requests</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -425,19 +426,19 @@ const UsersView = () => {
<th>LeaveType</th>
<th>Type</th>
<th>RequestKind</th>
<th>Kind</th>
<th>StartsAt</th>
<th>Start</th>
<th>EndsAt</th>
<th>Finish</th>
@ -453,15 +454,15 @@ const UsersView = () => {
<th>RequiresApproval</th>
<th>Requires Approval</th>
<th>SubmittedAt</th>
<th>Submitted At</th>
<th>DecidedAt</th>
<th>Decided At</th>
@ -469,13 +470,13 @@ const UsersView = () => {
<th>ManagerNote</th>
<th>Manager Note</th>
<th>ExternalReference</th>
<th>External Reference</th>
</tr>
@ -491,7 +492,7 @@ const UsersView = () => {
<td data-label="leave_type">
{ item.leave_type }
{ leaveTypeLabels[item.leave_type] || item.leave_type }
</td>
@ -579,7 +580,7 @@ const UsersView = () => {
</>
<>
<p className={'block font-bold mb-2'}>Time_off_requests Approver</p>
<p className={'block font-bold mb-2'}>Approvals</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -594,19 +595,19 @@ const UsersView = () => {
<th>LeaveType</th>
<th>Type</th>
<th>RequestKind</th>
<th>Kind</th>
<th>StartsAt</th>
<th>Start</th>
<th>EndsAt</th>
<th>Finish</th>
@ -622,15 +623,15 @@ const UsersView = () => {
<th>RequiresApproval</th>
<th>Requires Approval</th>
<th>SubmittedAt</th>
<th>Submitted At</th>
<th>DecidedAt</th>
<th>Decided At</th>
@ -638,13 +639,13 @@ const UsersView = () => {
<th>ManagerNote</th>
<th>Manager Note</th>
<th>ExternalReference</th>
<th>External Reference</th>
</tr>
@ -660,7 +661,7 @@ const UsersView = () => {
<td data-label="leave_type">
{ item.leave_type }
{ leaveTypeLabels[item.leave_type] || item.leave_type }
</td>
@ -749,7 +750,7 @@ const UsersView = () => {
<>
<p className={'block font-bold mb-2'}>Pto_journal_entries User</p>
<p className={'block font-bold mb-2'}>Time Off History</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -764,35 +765,35 @@ const UsersView = () => {
<th>EntryType</th>
<th>Entry Type</th>
<th>LeaveBucket</th>
<th>Leave Bucket</th>
<th>EffectiveAt</th>
<th>Effective At</th>
<th>CalendarYear</th>
<th>Calendar Year</th>
<th>AmountHours</th>
<th>Amount Hours</th>
<th>AmountDays</th>
<th>Amount Days</th>
<th>CountsAgainstBalance</th>
<th>Counts Against Balance</th>
<th>PostingStatus</th>
<th>Posting Status</th>
@ -802,7 +803,7 @@ const UsersView = () => {
<th>EnteredAt</th>
<th>Entered At</th>
</tr>
@ -824,7 +825,7 @@ const UsersView = () => {
<td data-label="leave_bucket">
{ item.leave_bucket }
{ leaveTypeLabels[item.leave_bucket] || item.leave_bucket }
</td>
@ -888,7 +889,7 @@ const UsersView = () => {
</>
<>
<p className={'block font-bold mb-2'}>Pto_journal_entries EnteredBy</p>
<p className={'block font-bold mb-2'}>Time Off Entries Created</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -903,35 +904,35 @@ const UsersView = () => {
<th>EntryType</th>
<th>Entry Type</th>
<th>LeaveBucket</th>
<th>Leave Bucket</th>
<th>EffectiveAt</th>
<th>Effective At</th>
<th>CalendarYear</th>
<th>Calendar Year</th>
<th>AmountHours</th>
<th>Amount Hours</th>
<th>AmountDays</th>
<th>Amount Days</th>
<th>CountsAgainstBalance</th>
<th>Counts Against Balance</th>
<th>PostingStatus</th>
<th>Posting Status</th>
@ -941,7 +942,7 @@ const UsersView = () => {
<th>EnteredAt</th>
<th>Entered At</th>
</tr>
@ -963,7 +964,7 @@ const UsersView = () => {
<td data-label="leave_bucket">
{ item.leave_bucket }
{ leaveTypeLabels[item.leave_bucket] || item.leave_bucket }
</td>
@ -1028,7 +1029,7 @@ const UsersView = () => {
<>
<p className={'block font-bold mb-2'}>Yearly_leave_summaries User</p>
<p className={'block font-bold mb-2'}>Yearly Leave Summary</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -1041,39 +1042,39 @@ const UsersView = () => {
<th>CalendarYear</th>
<th>Calendar Year</th>
<th>PTOPendingDays</th>
<th>PTO Pending</th>
<th>PTOScheduledDays</th>
<th>PTO Scheduled</th>
<th>PTOTakenDays</th>
<th>PTO Taken</th>
<th>PTOAvailableDays</th>
<th>PTO Available</th>
<th>MedicalTakenDays</th>
<th>Medical Taken</th>
<th>BereavementTakenDays</th>
<th>Bereavement Taken</th>
<th>TimeInLieuAvailableDays</th>
<th>Time In Lieu Available</th>
<th>VacationPayPaidAmount</th>
<th>Vacation Pay Paid</th>
</tr>
@ -1150,7 +1151,7 @@ const UsersView = () => {
<>
<p className={'block font-bold mb-2'}>Office_calendar_events User</p>
<p className={'block font-bold mb-2'}>Calendar Events</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -1161,7 +1162,7 @@ const UsersView = () => {
<tr>
<th>EventType</th>
<th>Event Type</th>
@ -1175,15 +1176,15 @@ const UsersView = () => {
<th>StartsAt</th>
<th>Start</th>
<th>EndsAt</th>
<th>Finish</th>
<th>IsAllDay</th>
<th>All Day</th>
@ -1250,7 +1251,7 @@ const UsersView = () => {
<>
<p className={'block font-bold mb-2'}>Approval_tasks AssignedManager</p>
<p className={'block font-bold mb-2'}>Approval Tasks</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -1269,11 +1270,11 @@ const UsersView = () => {
<th>DueAt</th>
<th>Due At</th>
<th>CompletedAt</th>
<th>Completed At</th>

View File

@ -26,6 +26,14 @@ const Yearly_leave_summariesView = () => {
const dispatch = useAppDispatch()
const { yearly_leave_summaries } = useAppSelector((state) => state.yearly_leave_summaries)
const getUserLabel = (user: any) => {
if (!user) return '';
if (user.label) return user.label;
if (user.firstName || user.lastName) {
return `${user.firstName || ''} ${user.lastName || ''}`.trim();
}
return user.id || '';
}
const { id } = router.query;
@ -42,10 +50,10 @@ const Yearly_leave_summariesView = () => {
return (
<>
<Head>
<title>{getPageTitle('View yearly_leave_summaries')}</title>
<title>{getPageTitle('View Yearly Leave Summary')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View yearly_leave_summaries')} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'View Yearly Leave Summary'} main>
<BaseButton
color='info'
label='Edit'
@ -79,7 +87,7 @@ const Yearly_leave_summariesView = () => {
<p className={'block font-bold mb-2'}>User</p>
<p>{yearly_leave_summaries?.user?.firstName ?? 'No data'}</p>
<p>{getUserLabel(yearly_leave_summaries?.user) || 'No data'}</p>
@ -119,7 +127,7 @@ const Yearly_leave_summariesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>CalendarYear</p>
<p className={'block font-bold mb-2'}>Calendar Year</p>
<p>{yearly_leave_summaries?.calendar_year || 'No data'}</p>
</div>
@ -151,7 +159,7 @@ const Yearly_leave_summariesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>PTOPendingDays</p>
<p className={'block font-bold mb-2'}>PTO Pending</p>
<p>{yearly_leave_summaries?.pto_pending_days || 'No data'}</p>
</div>
@ -183,7 +191,7 @@ const Yearly_leave_summariesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>PTOScheduledDays</p>
<p className={'block font-bold mb-2'}>PTO Scheduled</p>
<p>{yearly_leave_summaries?.pto_scheduled_days || 'No data'}</p>
</div>
@ -215,7 +223,7 @@ const Yearly_leave_summariesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>PTOTakenDays</p>
<p className={'block font-bold mb-2'}>PTO Taken</p>
<p>{yearly_leave_summaries?.pto_taken_days || 'No data'}</p>
</div>
@ -247,7 +255,7 @@ const Yearly_leave_summariesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>PTOAvailableDays</p>
<p className={'block font-bold mb-2'}>PTO Available</p>
<p>{yearly_leave_summaries?.pto_available_days || 'No data'}</p>
</div>
@ -279,7 +287,7 @@ const Yearly_leave_summariesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>MedicalTakenDays</p>
<p className={'block font-bold mb-2'}>Medical Taken</p>
<p>{yearly_leave_summaries?.medical_taken_days || 'No data'}</p>
</div>
@ -311,7 +319,7 @@ const Yearly_leave_summariesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>BereavementTakenDays</p>
<p className={'block font-bold mb-2'}>Bereavement Taken</p>
<p>{yearly_leave_summaries?.bereavement_taken_days || 'No data'}</p>
</div>
@ -343,7 +351,7 @@ const Yearly_leave_summariesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>TimeInLieuAvailableDays</p>
<p className={'block font-bold mb-2'}>Time In Lieu Available</p>
<p>{yearly_leave_summaries?.time_in_lieu_available_days || 'No data'}</p>
</div>
@ -375,7 +383,7 @@ const Yearly_leave_summariesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>VacationPayPaidAmount</p>
<p className={'block font-bold mb-2'}>Vacation Pay Paid</p>
<p>{yearly_leave_summaries?.vacation_pay_paid_amount || 'No data'}</p>
</div>