refactor: clean up code formatting and improve readability
- Standardized table formatting in `api.md` for privilege keys, enhancing clarity. - Removed unnecessary line breaks and improved inline formatting in various components, including `right-section.tsx`, `company-settings.remote.service.ts`, and `timeline-helpers.tsx`, to streamline code readability. - Updated test cases in `privilege-key-hierarchy.test.ts` and `filter-menu-by-view-privilege.test.ts` for better alignment and consistency in assertions. These changes improve the overall code quality and maintainability, making it easier for developers to navigate and understand the codebase.
This commit is contained in:
@@ -104,12 +104,6 @@ export function RightSection() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-[13px] text-center text-gray-600 mt-6 max-w-[85%] z-10 leading-[1.6]">
|
||||
Compatible with{' '}
|
||||
<span className="font-bold italic text-gray-900">Gmail, Outlook Web, LinkedIn and most web editors</span> for a
|
||||
smooth writing experience anywhere online.
|
||||
</p>
|
||||
|
||||
{/* Pagination Indicators */}
|
||||
<div className="flex gap-1.5 mt-8 z-10 mb-2">
|
||||
<div className="w-6 h-1 rounded-full bg-brand-500"></div>
|
||||
|
||||
+1
-4
@@ -1,8 +1,5 @@
|
||||
import type { AxiosInstance } from '@repo/core-api/http-client';
|
||||
import type {
|
||||
CompanySettingsEntity,
|
||||
UpdateCompanySettingsPayload,
|
||||
} from '../domain/entities/company-settings.entity';
|
||||
import type { CompanySettingsEntity, UpdateCompanySettingsPayload } from '../domain/entities/company-settings.entity';
|
||||
|
||||
export class CompanySettingsRemoteService {
|
||||
constructor(private readonly client: AxiosInstance) {}
|
||||
|
||||
+1
-4
@@ -1,10 +1,7 @@
|
||||
import { BaseDataTransformer } from '@repo/core-api/data-services';
|
||||
import { apiClient } from '../../../../../../../core/lib/api-client';
|
||||
import { TrackGoRemoteDataServices } from '../../../../../../../core/lib/trackgo-remote-data-services';
|
||||
import {
|
||||
companySettingsModuleConfig,
|
||||
type CompanySettingsShellEntity,
|
||||
} from '../constants/company-settings.constants';
|
||||
import { companySettingsModuleConfig, type CompanySettingsShellEntity } from '../constants/company-settings.constants';
|
||||
import { CompanySettingsRemoteService } from '../../data/company-settings.remote.service';
|
||||
|
||||
class CompanySettingsShellTransformer extends BaseDataTransformer<CompanySettingsShellEntity> {
|
||||
|
||||
+1
-4
@@ -25,10 +25,7 @@ export default function CompanySettingsModule() {
|
||||
>
|
||||
<Routes>
|
||||
<Route path="/index" element={<IndexPage />} />
|
||||
<Route
|
||||
path="/"
|
||||
element={<Navigate to={`${companySettingsModuleConfig.webUrl}/index`} replace />}
|
||||
/>
|
||||
<Route path="/" element={<Navigate to={`${companySettingsModuleConfig.webUrl}/index`} replace />} />
|
||||
<Route path="*" element={<Navigate to="/404" replace />} />
|
||||
</Routes>
|
||||
</EnterpriseModuleProvider>
|
||||
|
||||
+1
-5
@@ -91,11 +91,7 @@ export default function CompanySettingsPage() {
|
||||
<Stack gap="md" component="form" onSubmit={onSubmit}>
|
||||
<Grid gutter="md">
|
||||
<Grid.Col span={{ base: 12, md: 6 }}>
|
||||
<FieldDatePicker
|
||||
control={form.control}
|
||||
name="cycleStartDate"
|
||||
label={t('fields.cycleStartDate')}
|
||||
/>
|
||||
<FieldDatePicker control={form.control} name="cycleStartDate" label={t('fields.cycleStartDate')} />
|
||||
</Grid.Col>
|
||||
<Grid.Col span={{ base: 12, md: 6 }}>
|
||||
<FieldNumberInput
|
||||
|
||||
+1
-3
@@ -49,9 +49,7 @@ export function TimelineActivityList({
|
||||
radius="md"
|
||||
shadow={selected ? 'sm' : undefined}
|
||||
style={{
|
||||
borderColor: selected
|
||||
? 'var(--mantine-color-blue-filled)'
|
||||
: 'var(--mantine-color-default-border)',
|
||||
borderColor: selected ? 'var(--mantine-color-blue-filled)' : 'var(--mantine-color-default-border)',
|
||||
borderWidth: selected ? 2 : 1,
|
||||
}}
|
||||
>
|
||||
|
||||
+1
-8
@@ -1,12 +1,5 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import {
|
||||
Paper,
|
||||
ScrollArea,
|
||||
SegmentedControl,
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
} from '@repo/ui/components';
|
||||
import { Paper, ScrollArea, SegmentedControl, Stack, Text, TextInput } from '@repo/ui/components';
|
||||
import { Search } from 'lucide-react';
|
||||
import { TimelineActivityList } from './timeline-activity-list';
|
||||
import type { TimelineActivityGroup, TimelineActivityTab } from './timeline-helpers';
|
||||
|
||||
+3
-1
@@ -115,7 +115,9 @@ describe('timeline helpers', () => {
|
||||
'visit-1',
|
||||
'ungrouped',
|
||||
]);
|
||||
expect(filterActivityGroups(groups, { tab: 'completed', query: '' }).map((group) => group.key)).toEqual(['visit-2']);
|
||||
expect(filterActivityGroups(groups, { tab: 'completed', query: '' }).map((group) => group.key)).toEqual([
|
||||
'visit-2',
|
||||
]);
|
||||
expect(filterActivityGroups(groups, { tab: 'on_the_way', query: 'maju' }).map((group) => group.title)).toEqual([
|
||||
'Toko Maju',
|
||||
]);
|
||||
|
||||
+4
-16
@@ -1,7 +1,4 @@
|
||||
import type {
|
||||
TimelineActivityEntity,
|
||||
TimelineFootprintEntity,
|
||||
} from '../../domain/entities/timeline.entity';
|
||||
import type { TimelineActivityEntity, TimelineFootprintEntity } from '../../domain/entities/timeline.entity';
|
||||
|
||||
export type TimelineActivityGroup = {
|
||||
key: string;
|
||||
@@ -46,9 +43,7 @@ export function groupActivities(activities: TimelineActivityEntity[]): TimelineA
|
||||
const sorted = sortByRecordedAt(items);
|
||||
const last = sorted[sorted.length - 1];
|
||||
const first = sorted[0];
|
||||
const title =
|
||||
last?.customer?.name ??
|
||||
(key === 'ungrouped' ? 'ungrouped' : (last?.customer?.code ?? key));
|
||||
const title = last?.customer?.name ?? (key === 'ungrouped' ? 'ungrouped' : (last?.customer?.code ?? key));
|
||||
|
||||
return {
|
||||
key,
|
||||
@@ -95,10 +90,7 @@ export function resolvePlaybackPositions(
|
||||
return [];
|
||||
}
|
||||
|
||||
const latestByEmployee = new Map<
|
||||
string,
|
||||
{ latitude: number; longitude: number; label: string }
|
||||
>();
|
||||
const latestByEmployee = new Map<string, { latitude: number; longitude: number; label: string }>();
|
||||
|
||||
for (const footprint of footprints) {
|
||||
if (footprint.recordedAt > playbackTime) {
|
||||
@@ -155,10 +147,6 @@ export function shouldRestartPlayback(
|
||||
return playbackTime === null || playbackTime >= bounds.max;
|
||||
}
|
||||
|
||||
export function advancePlaybackTime(
|
||||
current: number,
|
||||
bounds: { min: number; max: number },
|
||||
step: number,
|
||||
): number {
|
||||
export function advancePlaybackTime(current: number, bounds: { min: number; max: number }, step: number): number {
|
||||
return Math.min(bounds.max, current + step);
|
||||
}
|
||||
|
||||
+1
-4
@@ -104,10 +104,7 @@ export function TimelinePlaybackOverlay({
|
||||
value={last ? `${formatClock(last.recordedAt)} · ${activityLabel(last.type)}` : '—'}
|
||||
/>
|
||||
<OverlayMetric label={currentLocationLabel} value={currentLocation || '—'} />
|
||||
<OverlayMetric
|
||||
label={activitiesLabel}
|
||||
value={group ? String(group.activities.length) : '—'}
|
||||
/>
|
||||
<OverlayMetric label={activitiesLabel} value={group ? String(group.activities.length) : '—'} />
|
||||
</SimpleGrid>
|
||||
</Stack>
|
||||
|
||||
|
||||
@@ -25,10 +25,7 @@ export default function SalesTimelineModule() {
|
||||
>
|
||||
<Routes>
|
||||
<Route path="/index" element={<IndexPage />} />
|
||||
<Route
|
||||
path="/"
|
||||
element={<Navigate to={`${salesTimelineModuleConfig.webUrl}/index`} replace />}
|
||||
/>
|
||||
<Route path="/" element={<Navigate to={`${salesTimelineModuleConfig.webUrl}/index`} replace />} />
|
||||
<Route path="*" element={<Navigate to="/404" replace />} />
|
||||
</Routes>
|
||||
</EnterpriseModuleProvider>
|
||||
|
||||
+4
-18
@@ -153,10 +153,7 @@ export default function TimelinePage() {
|
||||
[footprints, playbackTime],
|
||||
);
|
||||
const groups = useMemo(() => groupActivities(visibleActivities), [visibleActivities]);
|
||||
const filteredGroups = useMemo(
|
||||
() => filterActivityGroups(groups, { tab, query: search }),
|
||||
[groups, search, tab],
|
||||
);
|
||||
const filteredGroups = useMemo(() => filterActivityGroups(groups, { tab, query: search }), [groups, search, tab]);
|
||||
|
||||
useEffect(() => {
|
||||
if (filteredGroups.length === 0) {
|
||||
@@ -179,9 +176,7 @@ export default function TimelinePage() {
|
||||
);
|
||||
const focusPositions = useMemo(() => {
|
||||
if (selectedGroup && selectedGroup.activities.length > 0) {
|
||||
return selectedGroup.activities.map(
|
||||
(activity): [number, number] => [activity.latitude, activity.longitude],
|
||||
);
|
||||
return selectedGroup.activities.map((activity): [number, number] => [activity.latitude, activity.longitude]);
|
||||
}
|
||||
return dayPositions;
|
||||
}, [dayPositions, selectedGroup]);
|
||||
@@ -195,10 +190,7 @@ export default function TimelinePage() {
|
||||
})),
|
||||
[visibleFootprints],
|
||||
);
|
||||
const activityLabel = useCallback(
|
||||
(type: string) => t(`activities.types.${type}`, { defaultValue: type }),
|
||||
[t],
|
||||
);
|
||||
const activityLabel = useCallback((type: string) => t(`activities.types.${type}`, { defaultValue: type }), [t]);
|
||||
const mapActivities = useMemo(
|
||||
() =>
|
||||
visibleActivities.map((activity) => ({
|
||||
@@ -282,13 +274,7 @@ export default function TimelinePage() {
|
||||
</Box>
|
||||
</FormProvider>
|
||||
|
||||
<Box
|
||||
pos="absolute"
|
||||
bottom={16}
|
||||
left={{ base: 12, md: 432 }}
|
||||
right={{ base: 12, md: 16 }}
|
||||
style={{ zIndex: 2 }}
|
||||
>
|
||||
<Box pos="absolute" bottom={16} left={{ base: 12, md: 432 }} right={{ base: 12, md: 16 }} style={{ zIndex: 2 }}>
|
||||
<TimelinePlaybackOverlay
|
||||
group={selectedGroup}
|
||||
ungroupedLabel={t('activities.ungrouped')}
|
||||
|
||||
+3
-11
@@ -52,14 +52,9 @@ describe('groupPrivilegeKeys', () => {
|
||||
|
||||
expect(grouped.map((tab) => tab.group)).toEqual(['ADMIN', 'MOBILE']);
|
||||
expect(grouped[0]?.parents[0]?.parent).toBe('SALES');
|
||||
expect(grouped[0]?.parents[0]?.modules.map((m) => m.module)).toEqual([
|
||||
'ACTIVITIES',
|
||||
'DATA',
|
||||
]);
|
||||
expect(grouped[0]?.parents[0]?.modules.map((m) => m.module)).toEqual(['ACTIVITIES', 'DATA']);
|
||||
expect(grouped[1]?.parents[0]?.modules[0]?.directRow?.code).toBe('MOBILE.SALES.PLAN');
|
||||
expect(grouped[1]?.parents[0]?.modules[0]?.submodules[0]?.code).toBe(
|
||||
'MOBILE.SALES.PLAN.ATTENDANCE',
|
||||
);
|
||||
expect(grouped[1]?.parents[0]?.modules[0]?.submodules[0]?.code).toBe('MOBILE.SALES.PLAN.ATTENDANCE');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -72,10 +67,7 @@ describe('flattenParentSectionRows', () => {
|
||||
expect(salesParent).toBeDefined();
|
||||
const tableRows = flattenParentSectionRows(salesParent!);
|
||||
|
||||
expect(tableRows.map((r) => r.code)).toEqual([
|
||||
'ADMIN.SALES.DATA.CYCLE',
|
||||
'ADMIN.SALES.ACTIVITIES.PLAN',
|
||||
]);
|
||||
expect(tableRows.map((r) => r.code)).toEqual(['ADMIN.SALES.DATA.CYCLE', 'ADMIN.SALES.ACTIVITIES.PLAN']);
|
||||
expect(tableRows[0]).toMatchObject({ module: 'DATA', submodule: 'CYCLE' });
|
||||
expect(tableRows[1]).toMatchObject({ module: 'ACTIVITIES', submodule: 'PLAN' });
|
||||
});
|
||||
|
||||
+3
-15
@@ -28,10 +28,7 @@ function segmentLabel(t: (key: string) => string, kind: string, value: string) {
|
||||
return translated === key ? formatPrivilegeSegment(value) : translated;
|
||||
}
|
||||
|
||||
function submoduleCellLabel(
|
||||
t: (key: string) => string,
|
||||
row: PrivilegeTableRow,
|
||||
) {
|
||||
function submoduleCellLabel(t: (key: string) => string, row: PrivilegeTableRow) {
|
||||
if (row.submodule) {
|
||||
return row.label || segmentLabel(t, 'submodule', row.submodule);
|
||||
}
|
||||
@@ -53,11 +50,7 @@ function MatrixActionCells({
|
||||
<Table.Td key={action} ta="center" w={ACTION_COL_WIDTH} miw={ACTION_COL_WIDTH} maw={ACTION_COL_WIDTH}>
|
||||
<Box display="flex" style={{ justifyContent: 'center', alignItems: 'center' }}>
|
||||
{mode === 'edit' && formControl ? (
|
||||
<FieldCheckbox
|
||||
control={formControl.control}
|
||||
name={`matrix.${row.keyId}.${action}`}
|
||||
label=""
|
||||
/>
|
||||
<FieldCheckbox control={formControl.control} name={`matrix.${row.keyId}.${action}`} label="" />
|
||||
) : row.cell[action] ? (
|
||||
<Check size={16} />
|
||||
) : (
|
||||
@@ -137,12 +130,7 @@ function ParentMatrixTable({
|
||||
);
|
||||
}
|
||||
|
||||
export function PrivilegeMatrixLayout({
|
||||
groups,
|
||||
t,
|
||||
mode,
|
||||
formControl,
|
||||
}: PrivilegeMatrixLayoutProps) {
|
||||
export function PrivilegeMatrixLayout({ groups, t, mode, formControl }: PrivilegeMatrixLayoutProps) {
|
||||
if (groups.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,9 @@ describe('enterpriseStorageAdapter', () => {
|
||||
return null;
|
||||
});
|
||||
|
||||
await expect(enterpriseStorageAdapter.getPrivileges('ADMIN.SETTINGS.USER.PRIVILEGES')).resolves.toEqual(defaultPrivileges);
|
||||
await expect(enterpriseStorageAdapter.getPrivileges('ADMIN.SETTINGS.USER.PRIVILEGES')).resolves.toEqual(
|
||||
defaultPrivileges,
|
||||
);
|
||||
await expect(enterpriseStorageAdapter.getPrivileges('UNKNOWN')).resolves.toEqual(defaultPrivileges);
|
||||
});
|
||||
|
||||
|
||||
@@ -94,7 +94,11 @@ describe('filterMenuByViewPrivilege', () => {
|
||||
},
|
||||
];
|
||||
|
||||
const filtered = filterMenuByViewPrivilege(menu, { 'ADMIN.SALES.ACTIVITIES.ORDER': { ...noPrivileges, ALLOW_VIEW: true } }, false);
|
||||
const filtered = filterMenuByViewPrivilege(
|
||||
menu,
|
||||
{ 'ADMIN.SALES.ACTIVITIES.ORDER': { ...noPrivileges, ALLOW_VIEW: true } },
|
||||
false,
|
||||
);
|
||||
|
||||
expect(filtered.find((item) => item.key === 'sales')?.children?.map((child) => child.key)).toEqual([
|
||||
'orders',
|
||||
|
||||
Reference in New Issue
Block a user