39157-vm/frontend/src/pages/admin-help.tsx
2026-04-13 02:52:45 +00:00

305 lines
12 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
mdiAccountCashOutline,
mdiCashRegister,
mdiClipboardCheckOutline,
mdiClipboardListOutline,
mdiCogOutline,
mdiHelpCircleOutline,
mdiOpenInNew,
mdiPlayCircleOutline,
mdiShieldCheckOutline,
} from '@mdi/js';
import Head from 'next/head';
import React, { ReactElement } from 'react';
import BaseButton from '../components/BaseButton';
import BaseDivider from '../components/BaseDivider';
import BaseIcon from '../components/BaseIcon';
import CardBox from '../components/CardBox';
import SectionMain from '../components/SectionMain';
import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton';
import { getPageTitle } from '../config';
import LayoutAuthenticated from '../layouts/Authenticated';
type HelpSection = {
id: string;
title: string;
icon: string;
summary: string;
steps: string[];
checks?: string[];
warning?: string;
href?: string;
hrefLabel?: string;
};
const helpSections: HelpSection[] = [
{
id: 'getting-started',
title: 'Getting started',
icon: mdiPlayCircleOutline,
summary:
'Use this as the admins quick-start routine before you begin assigning pay or creating payroll runs.',
steps: [
'Confirm your users, customers, vehicles, pay types, and workers comp classes are up to date.',
'Make sure employees know whether they should use Log Work or whether an admin is entering logs on their behalf.',
'Decide how often payroll should be run and which date range each payroll run should cover.',
'Review this help page the first few times so your workflow stays consistent.',
],
checks: [
'Users have the correct role and active account status.',
'Employees have at least one pay setup assigned before they start logging jobs.',
'Admins know which menu pages they will use most often: Users, Pay types, Employee pay types, All Job Logs, and Payroll runs.',
],
href: '/dashboard',
hrefLabel: 'Open Dashboard',
},
{
id: 'assign-employee-pay',
title: 'Assign employee pay',
icon: mdiAccountCashOutline,
summary:
'This links an employee to the pay option they are allowed to use on jobs.',
steps: [
'Open Employee pay types.',
'Create a new record and select the employee.',
'Choose the pay type you want that employee to use, such as hourly or commission.',
'Save the record and verify the employee can now select that pay option while logging work.',
'If an employee should have multiple valid pay options, add each allowed pay type as its own assignment.',
],
checks: [
'Use clear pay type names so employees can easily choose the right option while logging work.',
'Remove outdated assignments if an employee should no longer use an old rate or method.',
],
href: '/employee_pay_types/employee_pay_types-list',
hrefLabel: 'Open Employee Pay Types',
},
{
id: 'set-up-pay-types',
title: 'Set up pay types',
icon: mdiCogOutline,
summary:
'Pay types control how job pay is calculated. Keep these clean and intentional so payroll stays predictable.',
steps: [
'Open Pay types and review the existing list before adding a new one.',
'For hourly work, confirm the hourly rate is correct.',
'For commission-based work, confirm the commission percentage is correct.',
'Use consistent naming so admins and employees can tell similar pay types apart.',
'Save changes, then test a sample job log if the pay logic is new or changed.',
],
checks: [
'Avoid creating duplicate pay types with only slightly different names.',
'When changing a rate, double-check whether you should edit an existing pay type or create a new one for future use.',
],
href: '/pay_types/pay_types-list',
hrefLabel: 'Open Pay Types',
},
{
id: 'review-job-logs',
title: 'Review job logs before payroll',
icon: mdiClipboardCheckOutline,
summary:
'A quick review before payroll helps catch missing hours, wrong pay types, or incomplete client-paid amounts.',
steps: [
'Open All Job Logs and filter by the payroll period you are about to run.',
'Scan Employee Pay, hours, client paid, and pay type selections for anything that looks incorrect.',
'Open any questionable record and verify the employee, customer, vehicle, and work details.',
'Fix missing or incorrect values before creating the payroll run.',
],
checks: [
'Hourly jobs should have hours entered.',
'Commission jobs should have the client paid amount entered.',
'Employees should not have duplicate or accidental logs for the same work.',
],
href: '/job_logs/job_logs-list',
hrefLabel: 'Open All Job Logs',
},
{
id: 'run-payroll',
title: 'Run payroll',
icon: mdiCashRegister,
summary:
'Create a payroll run only after the logs in that date range look clean.',
steps: [
'Open Payroll runs and create a new run.',
'Set the payroll dates carefully so the run only includes the jobs you intend to pay.',
'Save the payroll run and review the generated results.',
'Open the payroll line items if you need job-by-job detail for what was included.',
'If totals look wrong, go back to the source job logs, correct them, and then rerun or recreate payroll as needed.',
],
checks: [
'Watch for an incorrect date range first; that is one of the most common causes of missing or extra pay.',
'If one employee total looks off, inspect that employees individual job logs before changing anything else.',
],
href: '/payroll_runs/payroll_runs-list',
hrefLabel: 'Open Payroll Runs',
},
{
id: 'check-results',
title: 'Check payroll results',
icon: mdiClipboardListOutline,
summary:
'After a run is created, verify the output before treating it as final.',
steps: [
'Review the payroll run totals and compare them with the expected workload for that period.',
'Open Payroll line items to confirm each employee has the right combination of job entries.',
'Spot-check a few records manually using the job log Employee Pay values and the live preview logic on the log form.',
'Use the Payroll Dashboard if you want a broader visual review of payroll activity.',
],
checks: [
'Investigate unusual spikes or drops before approving the numbers internally.',
'Keep a repeatable review routine so payroll checks stay consistent every pay period.',
],
href: '/reports',
hrefLabel: 'Open Payroll Dashboard',
},
{
id: 'troubleshooting',
title: 'Troubleshooting and common issues',
icon: mdiShieldCheckOutline,
summary:
'Use this checklist whenever the numbers do not look right or an employee cannot complete a job log correctly.',
steps: [
'If an employee cannot choose the right pay option, confirm the Employee pay types assignment exists.',
'If live pay looks wrong on a job log, verify the pay type values and the job fields used for that method.',
'If payroll totals look off, compare the payroll date range with the dates on the job logs included in the run.',
'If a commission total looks too low or too high, check the client paid amount on the job log first.',
'If an hourly total looks wrong, check hours entered and the selected hourly pay type.',
],
warning:
'Best practice: fix the source job log or pay setup first, then regenerate or recreate the payroll output instead of trying to explain away a mismatch later.',
href: '/payroll_line_items/payroll_line_items-list',
hrefLabel: 'Open Payroll Line Items',
},
];
const AdminHelpPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Admin Help')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton
icon={mdiHelpCircleOutline}
title='Admin Help'
main
>
{''}
</SectionTitleLineWithButton>
<CardBox className='mb-6'>
<div className='flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between'>
<div className='max-w-3xl'>
<h2 className='text-xl font-semibold mb-2'>Admin task checklist</h2>
<p className='text-gray-600 dark:text-gray-300'>
This page is a simple internal knowledge base for the most common admin workflows in the app.
Use the quick links below to jump to a process, then open the related page directly when you are ready to do the task.
</p>
</div>
<BaseButton
href='/payroll_runs/payroll_runs-list'
color='info'
icon={mdiOpenInNew}
label='Go to Payroll Runs'
/>
</div>
<BaseDivider />
<div className='flex flex-wrap gap-3'>
{helpSections.map((section) => (
<BaseButton
key={section.id}
asAnchor
href={`#${section.id}`}
color='whiteDark'
small
label={section.title}
/>
))}
</div>
</CardBox>
<div className='grid grid-cols-1 gap-6 xl:grid-cols-2'>
{helpSections.map((section) => (
<CardBox key={section.id} className='h-full'>
<div id={section.id} className='scroll-mt-20'>
<div className='flex items-start justify-between gap-4 mb-4'>
<div className='flex items-start gap-3'>
<BaseIcon path={section.icon} size={28} className='text-blue-600 dark:text-blue-400 mt-1' />
<div>
<h2 className='text-xl font-semibold'>{section.title}</h2>
<p className='text-sm text-gray-600 dark:text-gray-300 mt-1'>
{section.summary}
</p>
</div>
</div>
{section.href && section.hrefLabel ? (
<BaseButton
href={section.href}
color='info'
small
icon={mdiOpenInNew}
label={section.hrefLabel}
/>
) : null}
</div>
<div className='mb-4'>
<div className='text-sm font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400 mb-2'>
Checklist
</div>
<ol className='list-decimal pl-5 space-y-2 text-sm leading-6'>
{section.steps.map((step) => (
<li key={step}>{step}</li>
))}
</ol>
</div>
{section.checks?.length ? (
<div className='mb-4'>
<div className='text-sm font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400 mb-2'>
Verify before moving on
</div>
<ul className='list-disc pl-5 space-y-2 text-sm leading-6'>
{section.checks.map((check) => (
<li key={check}>{check}</li>
))}
</ul>
</div>
) : null}
{section.warning ? (
<div className='rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm leading-6 text-amber-900 dark:border-amber-500/40 dark:bg-amber-500/10 dark:text-amber-100'>
<span className='font-semibold'>Admin note:</span> {section.warning}
</div>
) : null}
</div>
</CardBox>
))}
</div>
<CardBox className='mt-6'>
<div className='flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between'>
<div>
<h2 className='text-lg font-semibold'>Suggested next improvement</h2>
<p className='text-sm text-gray-600 dark:text-gray-300 mt-1'>
If you want, this help page can later become searchable or editable so admins can maintain their own internal SOPs.
</p>
</div>
<BaseButton href='/dashboard' color='whiteDark' label='Back to Dashboard' />
</div>
</CardBox>
</SectionMain>
</>
);
};
AdminHelpPage.getLayout = function getLayout(page: ReactElement) {
return <LayoutAuthenticated permission='UPDATE_USERS'>{page}</LayoutAuthenticated>;
};
export default AdminHelpPage;