refactor: improve code formatting and organization across multiple components

- Enhanced readability by restructuring code formatting in various components, including API documentation, user management, and sales modules.
- Standardized table and object definitions for better clarity in API documentation.
- Improved layout and indentation in React components for better maintainability.
- Updated unit tests to reflect changes in formatting and ensure consistency.

These changes enhance the overall code quality and maintainability of the project, making it easier for developers to navigate and understand the codebase.
This commit is contained in:
shancheas
2026-08-27 13:09:57 +07:00
parent 105cf3030a
commit 6b012a6aae
44 changed files with 371 additions and 260 deletions
@@ -17,7 +17,9 @@ const { setView, panTo, invalidateSize } = vi.hoisted(() => ({
vi.mock('react-leaflet', () => ({
MapContainer: ({ children }: { children: React.ReactNode }) => <div data-testid="osm-map">{children}</div>,
TileLayer: () => <div data-testid="osm-tiles" />,
CircleMarker: ({ center }: { center: [number, number] }) => <div data-testid="location-marker">{`${center[0]},${center[1]}`}</div>,
CircleMarker: ({ center }: { center: [number, number] }) => (
<div data-testid="location-marker">{`${center[0]},${center[1]}`}</div>
),
useMap: () => ({ setView, panTo, invalidateSize }),
useMapEvents: (handlers: { click?: (event: LeafletClick) => void }) => {
mapClick = handlers.click;
@@ -123,10 +123,19 @@ export function LocationMap({
className="tg-map-viewport"
style={{ cursor: interactive ? 'crosshair' : undefined }}
>
<MapContainer center={center} zoom={zoom} style={{ height: '100%', width: '100%' }} scrollWheelZoom={interactive}>
<MapContainer
center={center}
zoom={zoom}
style={{ height: '100%', width: '100%' }}
scrollWheelZoom={interactive}
>
<TileLayer attribution={attribution} url={tileUrl} />
{position ? (
<CircleMarker center={position} radius={10} pathOptions={{ color: 'var(--mantine-color-blue-8)', fillOpacity: 0.9 }} />
<CircleMarker
center={position}
radius={10}
pathOptions={{ color: 'var(--mantine-color-blue-8)', fillOpacity: 0.9 }}
/>
) : null}
<SyncMapView latitude={latitude} longitude={longitude} lastPickedRef={lastPickedRef} />
{onChange ? <MapClickPicker onPick={handlePick} /> : null}
@@ -43,7 +43,7 @@ export function clampLatitude(value: number): number {
// which the form schemas reject. Keep 180 and -180 as authored instead of collapsing them.
export function wrapLongitude(value: number): number {
if (value >= -180 && value <= 180) return value;
const wrapped = ((value + 180) % 360 + 360) % 360 - 180;
const wrapped = ((((value + 180) % 360) + 360) % 360) - 180;
return wrapped;
}
@@ -54,10 +54,7 @@ export function locationFromLatLng(lat: number, lng: number): { latitude: number
};
}
export function mapViewForLocation(
latitude: unknown,
longitude: unknown,
): { center: [number, number]; zoom: number } {
export function mapViewForLocation(latitude: unknown, longitude: unknown): { center: [number, number]; zoom: number } {
const point = toLocationLatLng(latitude, longitude);
if (!point) {
return { center: DEFAULT_MAP_CENTER, zoom: DEFAULT_MAP_ZOOM };
+2 -2
View File
@@ -1,3 +1,3 @@
export const OSM_TILE_URL = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png';
export const OSM_ATTRIBUTION = '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
export const OSM_ATTRIBUTION =
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
@@ -7,7 +7,5 @@ export function toLeafletLatLngs(geometry?: RouteGeometry | null): Array<[number
if (!geometry?.coordinates?.length) {
return [];
}
return geometry.coordinates
.filter((pair) => Array.isArray(pair) && pair.length >= 2)
.map(([lng, lat]) => [lat, lng]);
return geometry.coordinates.filter((pair) => Array.isArray(pair) && pair.length >= 2).map(([lng, lat]) => [lat, lng]);
}
+6 -1
View File
@@ -44,7 +44,12 @@ export function RouteMap({ geometry, height = 280 }: RouteMapProps) {
<TileLayer attribution={OSM_ATTRIBUTION} url={OSM_TILE_URL} />
<Polyline positions={positions} pathOptions={{ color: 'var(--mantine-color-blue-6)', weight: 4 }} />
{positions.map((position, index) => (
<CircleMarker key={`${position[0]}-${position[1]}-${index}`} center={position} radius={8} pathOptions={{ color: 'var(--mantine-color-blue-8)' }}>
<CircleMarker
key={`${position[0]}-${position[1]}-${index}`}
center={position}
radius={8}
pathOptions={{ color: 'var(--mantine-color-blue-8)' }}
>
<Tooltip permanent>{index + 1}</Tooltip>
</CircleMarker>
))}
@@ -1,24 +1,17 @@
import { describe, expect, it } from 'vitest';
import { DateUtils } from '@repo/utils';
import {
EMPTY_AUDIT_DISPLAY,
formatAuditActor,
formatAuditTimestamp,
resolveAuditValue,
} from './audit-column.utils';
import { EMPTY_AUDIT_DISPLAY, formatAuditActor, formatAuditTimestamp, resolveAuditValue } from './audit-column.utils';
describe('resolveAuditValue', () => {
it('prefers camelCase over snake_case', () => {
expect(
resolveAuditValue({ createdBy: 'alice', creator_name: 'legacy' }, 'createdBy', 'creator_name'),
).toBe('alice');
expect(resolveAuditValue({ createdBy: 'alice', creator_name: 'legacy' }, 'createdBy', 'creator_name')).toBe(
'alice',
);
});
it('falls back to snake_case when camelCase is missing', () => {
expect(resolveAuditValue({ creator_name: 'legacy' }, 'createdBy', 'creator_name')).toBe('legacy');
expect(resolveAuditValue({ created_at: 1_700_000_000_000 }, 'createdAt', 'created_at')).toBe(
1_700_000_000_000,
);
expect(resolveAuditValue({ created_at: 1_700_000_000_000 }, 'createdAt', 'created_at')).toBe(1_700_000_000_000);
});
it('returns undefined when neither field is present', () => {
@@ -63,7 +63,10 @@ export function BulkActionMenu({
const hasActive = selectedRows.some((row) => row[statusKey]?.toLowerCase() === 'active');
const hasInactive = selectedRows.some(
(row) => row[statusKey]?.toLowerCase() === 'inactive' || row[statusKey]?.toLowerCase() === 'draft' || row[statusKey]?.toLowerCase() === 'archived',
(row) =>
row[statusKey]?.toLowerCase() === 'inactive' ||
row[statusKey]?.toLowerCase() === 'draft' ||
row[statusKey]?.toLowerCase() === 'archived',
);
const defaultActions: PageActionProps[] = [];
@@ -282,7 +282,7 @@ export function EnterpriseDataTable<E extends BaseEntity>(props: EnterpriseDataT
const filterKeys = filterConfig?.defaultValues
? Object.keys(filterConfig.defaultValues)
: Object.keys(filterData).filter(
(key) => key !== searchKey && !['page', 'limit', 'order_by', 'order_type'].includes(key),
(key) => key !== searchKey && !['page', 'limit', 'orderBy', 'orderType'].includes(key),
);
return filterKeys.filter((key) => {
@@ -773,8 +773,8 @@ export function EnterpriseDataTable<E extends BaseEntity>(props: EnterpriseDataT
const requestParams: Record<string, any> = {
page,
limit,
order_by: orderBy,
order_type: orderType,
orderBy: orderBy,
orderType: orderType,
...filterRef.current,
};
@@ -504,7 +504,8 @@ export function EnterpriseDetailPageProvider<E extends BaseEntity = BaseEntity>(
const isMasterData = moduleType === 'MASTER_DATA';
const isDataActive = detailData && ['active'].includes(detailData[statusKey]?.toLowerCase());
const isDataInActive = detailData && ['inactive', 'draft', 'archived'].includes(detailData[statusKey]?.toLowerCase());
const isDataInActive =
detailData && ['inactive', 'draft', 'archived'].includes(detailData[statusKey]?.toLowerCase());
// 1. Declare action with Privilege & Module Type conditions directly
const rawActions = [