Merge pull request 'refactor: restructure storage and environment modules; remove unused code' (#14) from feat/layout-web into main
Reviewed-on: eigen/fe-monorepo-template#14
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { CommonRemoteDataServices } from '@repo/core-api/data-services';
|
import { CommonRemoteDataServices } from '@repo/core-api/data-services';
|
||||||
import type { BaseEntity } from '@repo/core-api/data-services';
|
import type { BaseEntity } from '@repo/core-api/data-services';
|
||||||
import { publicClient } from '../../../lib/api-client';
|
import { publicClient } from '../../../core/lib/api-client';
|
||||||
|
|
||||||
// ─── Domain Entity ──────────────────────────────────────────────
|
// ─── Domain Entity ──────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -31,10 +31,7 @@ export interface PublicContentEntity extends BaseEntity {
|
|||||||
* const { data: post } = await publicContentServices.getOne('hello-world');
|
* const { data: post } = await publicContentServices.getOne('hello-world');
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export const publicContentServices = new CommonRemoteDataServices<PublicContentEntity>(
|
export const publicContentServices = new CommonRemoteDataServices<PublicContentEntity>(publicClient, {
|
||||||
publicClient,
|
|
||||||
{
|
|
||||||
apiUrl: '/content',
|
apiUrl: '/content',
|
||||||
moduleKey: 'PUBLIC_CONTENT',
|
moduleKey: 'PUBLIC_CONTENT',
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ import { useEffect, useState } from 'react';
|
|||||||
import { useTranslation, changeLanguage, i18n } from '@repo/core-i18n';
|
import { useTranslation, changeLanguage, i18n } from '@repo/core-i18n';
|
||||||
|
|
||||||
// Decentralized locale imports
|
// Decentralized locale imports
|
||||||
import homeId from '../locales/id/home.json';
|
import homeId from '../core/locales/id/home.json';
|
||||||
import homeEn from '../locales/en/home.json';
|
import homeEn from '../core/locales/en/home.json';
|
||||||
|
|
||||||
// Bendera penanda statis di level modul (default: false)
|
// Bendera penanda statis di level modul (default: false)
|
||||||
let isHomeDictLoaded = false;
|
let isHomeDictLoaded = false;
|
||||||
|
|||||||
Vendored
+1
-1
@@ -7,7 +7,7 @@ import homeEn from '../locales/en/home.json';
|
|||||||
declare module 'react-i18next' {
|
declare module 'react-i18next' {
|
||||||
interface CustomTypeOptions {
|
interface CustomTypeOptions {
|
||||||
defaultNS: 'common';
|
defaultNS: 'common';
|
||||||
resources: typeof coreResources['en'] & {
|
resources: (typeof coreResources)['en'] & {
|
||||||
home: typeof homeEn;
|
home: typeof homeEn;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useAppEvent } from '@repo/core-events';
|
import { useAppEvent } from '@repo/core-events';
|
||||||
import type { ProfileUpdatedPayload } from '@repo/core-events';
|
import type { ProfileUpdatedPayload } from '@repo/core-events';
|
||||||
import { secureIndexedDB, AppStorageKey } from '../../../../core/storage';
|
import { secureIndexedDB, AppStorageKey } from '../../../../core/storage/local';
|
||||||
|
|
||||||
// ─── Props ──────────────────────────────────────────────────────
|
// ─── Props ──────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { CommonRemoteDataServices } from '@repo/core-api/data-services';
|
import { CommonRemoteDataServices } from '@repo/core-api/data-services';
|
||||||
import type { BaseEntity } from '@repo/core-api/data-services';
|
import type { BaseEntity } from '@repo/core-api/data-services';
|
||||||
import { apiClient } from '../../../../../../lib/api-client';
|
import { apiClient } from '../../../../../../core/lib/api-client';
|
||||||
|
|
||||||
// ─── Domain Entity ──────────────────────────────────────────────
|
// ─── Domain Entity ──────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -34,10 +34,7 @@ export interface BookingEntity extends BaseEntity {
|
|||||||
* await bookingServices.confirmProcessTransaction('42');
|
* await bookingServices.confirmProcessTransaction('42');
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export const bookingServices = new CommonRemoteDataServices<BookingEntity>(
|
export const bookingServices = new CommonRemoteDataServices<BookingEntity>(apiClient, {
|
||||||
apiClient,
|
|
||||||
{
|
|
||||||
apiUrl: '/bookings',
|
apiUrl: '/bookings',
|
||||||
moduleKey: 'BOOKING',
|
moduleKey: 'BOOKING',
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState, useEffect, useCallback } from 'react';
|
import { useState, useEffect, useCallback } from 'react';
|
||||||
import { useTranslation, changeLanguage, applyTenantOverrides, i18n } from '@repo/core-i18n';
|
import { useTranslation, changeLanguage, applyTenantOverrides, i18n } from '@repo/core-i18n';
|
||||||
import { secureIndexedDB, AppStorageKey } from '../../../../../../core/storage';
|
import { secureIndexedDB, AppStorageKey } from '../../../../../../core/storage/local';
|
||||||
|
|
||||||
// Decentralized locale imports
|
// Decentralized locale imports
|
||||||
import bookingId from '../locales/id/booking.json';
|
import bookingId from '../locales/id/booking.json';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useState, useCallback } from 'react';
|
import { useState, useCallback } from 'react';
|
||||||
import { secureStorage, secureIndexedDB, AppStorageKey } from '../../../../../../core/storage';
|
import { secureStorage, secureIndexedDB, AppStorageKey } from '../../../../../../core/storage/local';
|
||||||
|
|
||||||
// ─── Demo Data ──────────────────────────────────────────────────
|
// ─── Demo Data ──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,12 @@
|
|||||||
import { useEffect, useState, useCallback } from 'react';
|
import { useEffect, useState, useCallback } from 'react';
|
||||||
import {
|
import { Button, Card, Group, Stack, Title, Text, Table, Badge } from '@repo/ui/components';
|
||||||
Button,
|
|
||||||
Card,
|
import { itemDB, posConfigDB } from '../../core/storage/pouch-db';
|
||||||
Group,
|
import type { ItemEntity, POSConfigurationEntity } from '../../core/storage/pouch-db/entities';
|
||||||
Stack,
|
|
||||||
Title,
|
|
||||||
Text,
|
|
||||||
Table,
|
|
||||||
Badge,
|
|
||||||
} from '@repo/ui/components';
|
|
||||||
import { itemDB, posConfigDB } from '../../core/db';
|
|
||||||
import type { Item, POSConfiguration } from '../../core/db/types';
|
|
||||||
|
|
||||||
export default function PouchSample() {
|
export default function PouchSample() {
|
||||||
const [configs, setConfigs] = useState<POSConfiguration[]>([]);
|
const [configs, setConfigs] = useState<POSConfigurationEntity[]>([]);
|
||||||
const [items, setItems] = useState<Item[]>([]);
|
const [items, setItems] = useState<ItemEntity[]>([]);
|
||||||
|
|
||||||
// Load initial data
|
// Load initial data
|
||||||
const loadData = useCallback(async () => {
|
const loadData = useCallback(async () => {
|
||||||
@@ -24,7 +16,7 @@ export default function PouchSample() {
|
|||||||
|
|
||||||
const allItems = await itemDB.find({ selector: {} });
|
const allItems = await itemDB.find({ selector: {} });
|
||||||
setItems(allItems);
|
setItems(allItems);
|
||||||
console.log({allConfigs, allItems})
|
console.log({ allConfigs, allItems });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to load PouchDB data', err);
|
console.error('Failed to load PouchDB data', err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// 1. Import hooks yang baru saja dibuat Opus
|
// 1. Import hooks yang baru saja dibuat Opus
|
||||||
import { Button } from '@repo/ui/components';
|
import { Button } from '@repo/ui/components';
|
||||||
import { useElectronPrinter } from '../../hooks/use-electron-printer';
|
import { useElectronPrinter } from '../../core/hooks/use-electron-printer';
|
||||||
import { useElectronUpdater } from '../../hooks/use-electron-updater';
|
import { useElectronUpdater } from '../../core/hooks/use-electron-updater';
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
// 2. Panggil hooks-nya
|
// 2. Panggil hooks-nya
|
||||||
@@ -12,7 +12,9 @@ export default function App() {
|
|||||||
<div style={{ padding: '20px', border: '2px solid blue', margin: '20px' }}>
|
<div style={{ padding: '20px', border: '2px solid blue', margin: '20px' }}>
|
||||||
<h2>🧪 Test Integrasi Electron</h2>
|
<h2>🧪 Test Integrasi Electron</h2>
|
||||||
|
|
||||||
<p><strong>Status Auto-Update:</strong> {status}</p>
|
<p>
|
||||||
|
<strong>Status Auto-Update:</strong> {status}
|
||||||
|
</p>
|
||||||
|
|
||||||
<Button variant="filled" color="brand" onClick={refreshPrinters}>
|
<Button variant="filled" color="brand" onClick={refreshPrinters}>
|
||||||
Refresh Printer
|
Refresh Printer
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import {
|
|||||||
NumberInput,
|
NumberInput,
|
||||||
Textarea,
|
Textarea,
|
||||||
Switch,
|
Switch,
|
||||||
Radio,
|
|
||||||
Table,
|
Table,
|
||||||
Badge,
|
Badge,
|
||||||
Divider,
|
Divider,
|
||||||
@@ -48,13 +47,20 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
|||||||
|
|
||||||
const getSubtitle = () => {
|
const getSubtitle = () => {
|
||||||
switch (activeTab) {
|
switch (activeTab) {
|
||||||
case 'rbac': return 'Role-Based Access Control and Permissions';
|
case 'rbac':
|
||||||
case 'storage': return 'Offline-First PouchDB Synchronization';
|
return 'Role-Based Access Control and Permissions';
|
||||||
case 'auth': return 'Authentication & Security Layers';
|
case 'storage':
|
||||||
case 'ui-components': return 'Theme, Typography, Forms & Data Grids';
|
return 'Offline-First PouchDB Synchronization';
|
||||||
case 'events': return 'Global Event Bus Synchronization';
|
case 'auth':
|
||||||
case 'hardware': return 'Hardware Integration & Printers';
|
return 'Authentication & Security Layers';
|
||||||
default: return 'Architecture Showcase';
|
case 'ui-components':
|
||||||
|
return 'Theme, Typography, Forms & Data Grids';
|
||||||
|
case 'events':
|
||||||
|
return 'Global Event Bus Synchronization';
|
||||||
|
case 'hardware':
|
||||||
|
return 'Hardware Integration & Printers';
|
||||||
|
default:
|
||||||
|
return 'Architecture Showcase';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -74,7 +80,7 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
|||||||
minWidth: 260,
|
minWidth: 260,
|
||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
borderRight: '1px solid var(--mantine-color-default-border)',
|
borderRight: '1px solid var(--mantine-color-default-border)',
|
||||||
backgroundColor: 'var(--mantine-color-default-element-bg)'
|
backgroundColor: 'var(--mantine-color-default-element-bg)',
|
||||||
},
|
},
|
||||||
panel: { flex: 1, display: 'flex', flexDirection: 'column', height: '100vh', overflow: 'hidden' },
|
panel: { flex: 1, display: 'flex', flexDirection: 'column', height: '100vh', overflow: 'hidden' },
|
||||||
tab: { justifyContent: 'flex-start' }, // Ensure the entire tab content aligns left
|
tab: { justifyContent: 'flex-start' }, // Ensure the entire tab content aligns left
|
||||||
@@ -83,8 +89,12 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
|||||||
>
|
>
|
||||||
<Tabs.List>
|
<Tabs.List>
|
||||||
<Box mb="xl" px="sm">
|
<Box mb="xl" px="sm">
|
||||||
<Title order={3} c="brand.7">Eigen ERP</Title>
|
<Title order={3} c="brand.7">
|
||||||
<Text size="xs" c="dimmed">Architecture Showcase</Text>
|
Eigen ERP
|
||||||
|
</Title>
|
||||||
|
<Text size="xs" c="dimmed">
|
||||||
|
Architecture Showcase
|
||||||
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Tabs.Tab value="ui-components" leftSection={<Layout size={18} />}>
|
<Tabs.Tab value="ui-components" leftSection={<Layout size={18} />}>
|
||||||
@@ -118,13 +128,15 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
|||||||
borderLeft: 0,
|
borderLeft: 0,
|
||||||
borderRight: 0,
|
borderRight: 0,
|
||||||
zIndex: 10,
|
zIndex: 10,
|
||||||
flexShrink: 0
|
flexShrink: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Group justify="space-between">
|
<Group justify="space-between">
|
||||||
<Stack gap={0}>
|
<Stack gap={0}>
|
||||||
<Title order={3}>Architecture Showcase</Title>
|
<Title order={3}>Architecture Showcase</Title>
|
||||||
<Text size="sm" c="dimmed">{getSubtitle()}</Text>
|
<Text size="sm" c="dimmed">
|
||||||
|
{getSubtitle()}
|
||||||
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Group>
|
</Group>
|
||||||
</Paper>
|
</Paper>
|
||||||
@@ -132,25 +144,32 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
|||||||
{/* Scrollable Content Area */}
|
{/* Scrollable Content Area */}
|
||||||
<Box className="flex-1 overflow-y-auto p-6" style={{ height: 'calc(100vh - 80px)' }}>
|
<Box className="flex-1 overflow-y-auto p-6" style={{ height: 'calc(100vh - 80px)' }}>
|
||||||
<Container size="xl" m={0} p={0}>
|
<Container size="xl" m={0} p={0}>
|
||||||
|
|
||||||
{/* --- UI COMPONENTS TAB --- */}
|
{/* --- UI COMPONENTS TAB --- */}
|
||||||
{activeTab === 'ui-components' && (
|
{activeTab === 'ui-components' && (
|
||||||
<Stack gap="xl">
|
<Stack gap="xl">
|
||||||
{/* Control Panel */}
|
{/* Control Panel */}
|
||||||
<Card withBorder shadow="sm" radius="md" p="md">
|
<Card withBorder shadow="sm" radius="md" p="md">
|
||||||
<Title order={4} mb="md">Theme Controls</Title>
|
<Title order={4} mb="md">
|
||||||
|
Theme Controls
|
||||||
|
</Title>
|
||||||
<Group grow align="flex-end">
|
<Group grow align="flex-end">
|
||||||
<Select
|
<Select
|
||||||
label="Color Scheme"
|
label="Color Scheme"
|
||||||
value={colorScheme}
|
value={colorScheme}
|
||||||
onChange={(val) => setColorScheme((val as ColorSchemeType) || 'light')}
|
onChange={(val) => setColorScheme((val as ColorSchemeType) || 'light')}
|
||||||
data={[{ value: 'light', label: 'Light' }, { value: 'dark', label: 'Dark' }]}
|
data={[
|
||||||
|
{ value: 'light', label: 'Light' },
|
||||||
|
{ value: 'dark', label: 'Dark' },
|
||||||
|
]}
|
||||||
/>
|
/>
|
||||||
<Select
|
<Select
|
||||||
label="Density (Spacing & Sizing)"
|
label="Density (Spacing & Sizing)"
|
||||||
value={density}
|
value={density}
|
||||||
onChange={(val) => setDensity((val as DensityType) || 'standard')}
|
onChange={(val) => setDensity((val as DensityType) || 'standard')}
|
||||||
data={[{ value: 'compact', label: 'Compact (ERP Mode)' }, { value: 'standard', label: 'Standard (UI Mode)' }]}
|
data={[
|
||||||
|
{ value: 'compact', label: 'Compact (ERP Mode)' },
|
||||||
|
{ value: 'standard', label: 'Standard (UI Mode)' },
|
||||||
|
]}
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -159,22 +178,40 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
|||||||
<Card withBorder shadow="sm" radius="md" p="md">
|
<Card withBorder shadow="sm" radius="md" p="md">
|
||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
<div>
|
<div>
|
||||||
<Title order={4} mb="xs">Typography & Badges</Title>
|
<Title order={4} mb="xs">
|
||||||
<Text size="sm" c="dimmed">This is dimmed small text indicating a subtitle.</Text>
|
Typography & Badges
|
||||||
|
</Title>
|
||||||
|
<Text size="sm" c="dimmed">
|
||||||
|
This is dimmed small text indicating a subtitle.
|
||||||
|
</Text>
|
||||||
<Group mt="md">
|
<Group mt="md">
|
||||||
<Badge color="brand">Brand Badge</Badge>
|
<Badge color="brand">Brand Badge</Badge>
|
||||||
<Badge color="success" variant="light">Success Status</Badge>
|
<Badge color="success" variant="light">
|
||||||
<Badge color="error" variant="outline">Error State</Badge>
|
Success Status
|
||||||
|
</Badge>
|
||||||
|
<Badge color="error" variant="outline">
|
||||||
|
Error State
|
||||||
|
</Badge>
|
||||||
</Group>
|
</Group>
|
||||||
</div>
|
</div>
|
||||||
<Divider />
|
<Divider />
|
||||||
<div>
|
<div>
|
||||||
<Title order={4} mb="md">Buttons</Title>
|
<Title order={4} mb="md">
|
||||||
|
Buttons
|
||||||
|
</Title>
|
||||||
<Group>
|
<Group>
|
||||||
<Button variant="filled" color="brand">Filled Button</Button>
|
<Button variant="filled" color="brand">
|
||||||
<Button variant="outline" color="brand">Outline Button</Button>
|
Filled Button
|
||||||
<Button variant="light" color="info">Light Info</Button>
|
</Button>
|
||||||
<Button variant="subtle" color="error">Cancel</Button>
|
<Button variant="outline" color="brand">
|
||||||
|
Outline Button
|
||||||
|
</Button>
|
||||||
|
<Button variant="light" color="info">
|
||||||
|
Light Info
|
||||||
|
</Button>
|
||||||
|
<Button variant="subtle" color="error">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</div>
|
</div>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -182,7 +219,9 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
|||||||
|
|
||||||
{/* Forms */}
|
{/* Forms */}
|
||||||
<Card withBorder shadow="sm" radius="md" p="md">
|
<Card withBorder shadow="sm" radius="md" p="md">
|
||||||
<Title order={4} mb="md">Form Elements</Title>
|
<Title order={4} mb="md">
|
||||||
|
Form Elements
|
||||||
|
</Title>
|
||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
<Group grow align="flex-start">
|
<Group grow align="flex-start">
|
||||||
<TextInput label="First Name" placeholder="Enter your first name" withAsterisk />
|
<TextInput label="First Name" placeholder="Enter your first name" withAsterisk />
|
||||||
@@ -202,7 +241,9 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
|||||||
|
|
||||||
{/* Data Grid */}
|
{/* Data Grid */}
|
||||||
<Card withBorder shadow="sm" radius="md" p="md">
|
<Card withBorder shadow="sm" radius="md" p="md">
|
||||||
<Title order={4} mb="md">Data Grid</Title>
|
<Title order={4} mb="md">
|
||||||
|
Data Grid
|
||||||
|
</Title>
|
||||||
<Table striped highlightOnHover withTableBorder withColumnBorders>
|
<Table striped highlightOnHover withTableBorder withColumnBorders>
|
||||||
<Table.Thead>
|
<Table.Thead>
|
||||||
<Table.Tr>
|
<Table.Tr>
|
||||||
@@ -218,7 +259,12 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
|||||||
<Table.Td>{row.id}</Table.Td>
|
<Table.Td>{row.id}</Table.Td>
|
||||||
<Table.Td>{row.customer}</Table.Td>
|
<Table.Td>{row.customer}</Table.Td>
|
||||||
<Table.Td>
|
<Table.Td>
|
||||||
<Badge size="sm" color={row.status === 'Delivered' ? 'success' : row.status === 'Shipped' ? 'info' : 'warning'}>
|
<Badge
|
||||||
|
size="sm"
|
||||||
|
color={
|
||||||
|
row.status === 'Delivered' ? 'success' : row.status === 'Shipped' ? 'info' : 'warning'
|
||||||
|
}
|
||||||
|
>
|
||||||
{row.status}
|
{row.status}
|
||||||
</Badge>
|
</Badge>
|
||||||
</Table.Td>
|
</Table.Td>
|
||||||
@@ -242,7 +288,9 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
|||||||
{activeTab === 'rbac' && (
|
{activeTab === 'rbac' && (
|
||||||
<Stack gap="xl">
|
<Stack gap="xl">
|
||||||
<Card withBorder shadow="sm" radius="md" p="md">
|
<Card withBorder shadow="sm" radius="md" p="md">
|
||||||
<Title order={4} mb="md">RBAC Engine</Title>
|
<Title order={4} mb="md">
|
||||||
|
RBAC Engine
|
||||||
|
</Title>
|
||||||
<Text c="dimmed">RBAC Demo Component Coming Soon...</Text>
|
<Text c="dimmed">RBAC Demo Component Coming Soon...</Text>
|
||||||
</Card>
|
</Card>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -252,7 +300,9 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
|||||||
{activeTab === 'auth' && (
|
{activeTab === 'auth' && (
|
||||||
<Stack gap="xl">
|
<Stack gap="xl">
|
||||||
<Card withBorder shadow="sm" radius="md" p="md">
|
<Card withBorder shadow="sm" radius="md" p="md">
|
||||||
<Title order={4} mb="md">Auth & Security</Title>
|
<Title order={4} mb="md">
|
||||||
|
Auth & Security
|
||||||
|
</Title>
|
||||||
<Text c="dimmed">Auth Demo Component Coming Soon...</Text>
|
<Text c="dimmed">Auth Demo Component Coming Soon...</Text>
|
||||||
</Card>
|
</Card>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -262,7 +312,9 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
|||||||
{activeTab === 'events' && (
|
{activeTab === 'events' && (
|
||||||
<Stack gap="xl">
|
<Stack gap="xl">
|
||||||
<Card withBorder shadow="sm" radius="md" p="md">
|
<Card withBorder shadow="sm" radius="md" p="md">
|
||||||
<Title order={4} mb="md">Nested Showcase Example</Title>
|
<Title order={4} mb="md">
|
||||||
|
Nested Showcase Example
|
||||||
|
</Title>
|
||||||
<Text mb="md">This is an example of a nested showcase component.</Text>
|
<Text mb="md">This is an example of a nested showcase component.</Text>
|
||||||
<ExamplePage />
|
<ExamplePage />
|
||||||
</Card>
|
</Card>
|
||||||
@@ -280,7 +332,6 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
|||||||
</Card>
|
</Card>
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</Container>
|
</Container>
|
||||||
</Box>
|
</Box>
|
||||||
</Tabs.Panel>
|
</Tabs.Panel>
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
/**
|
|
||||||
* Enterprise ERP Data Domain Models
|
|
||||||
* These types reflect the actual schema of the underlying CouchDB instances.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export interface ItemRate {
|
|
||||||
season_period?: string | null;
|
|
||||||
price: string | number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ItemCategory {
|
|
||||||
_id?: string;
|
|
||||||
name?: string;
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a sellable product or service.
|
|
||||||
*/
|
|
||||||
export interface Item {
|
|
||||||
_id: string;
|
|
||||||
_rev?: string;
|
|
||||||
name: string;
|
|
||||||
base_price: string | number;
|
|
||||||
item_type: string;
|
|
||||||
usage_type?: string;
|
|
||||||
item_category?: ItemCategory[] | ItemCategory | string;
|
|
||||||
item_rates?: ItemRate[];
|
|
||||||
|
|
||||||
// Allow for other ERP-specific fields
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the configuration and assigned data for a specific Point of Sale terminal.
|
|
||||||
*/
|
|
||||||
export interface POSConfiguration {
|
|
||||||
_id: string;
|
|
||||||
_rev?: string;
|
|
||||||
pos_number: string;
|
|
||||||
pos_name: string;
|
|
||||||
items: Item[];
|
|
||||||
payment_methods?: any[];
|
|
||||||
|
|
||||||
// Allow for other ERP-specific fields
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export * from './item.pouchdb.entity';
|
||||||
|
export * from './pos-configuration.pouchdb.entity';
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
interface ItemRateEntity {
|
||||||
|
season_period?: string | null;
|
||||||
|
price: string | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ItemCategoryEntity {
|
||||||
|
_id?: string;
|
||||||
|
name?: string;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a sellable product or service.
|
||||||
|
*/
|
||||||
|
export interface ItemEntity {
|
||||||
|
_id: string;
|
||||||
|
_rev?: string;
|
||||||
|
name: string;
|
||||||
|
base_price: string | number;
|
||||||
|
item_type: string;
|
||||||
|
usage_type?: string;
|
||||||
|
item_category?: ItemCategoryEntity[] | ItemCategoryEntity | string;
|
||||||
|
item_rates?: ItemRateEntity[];
|
||||||
|
|
||||||
|
// Allow for other ERP-specific fields
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { ItemEntity } from './item.pouchdb.entity';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the configuration and assigned data for a specific Point of Sale terminal.
|
||||||
|
*/
|
||||||
|
export interface POSConfigurationEntity {
|
||||||
|
_id: string;
|
||||||
|
_rev?: string;
|
||||||
|
pos_number: string;
|
||||||
|
pos_name: string;
|
||||||
|
items: ItemEntity[];
|
||||||
|
payment_methods?: any[];
|
||||||
|
|
||||||
|
// Allow for other ERP-specific fields
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
@@ -5,9 +5,10 @@
|
|||||||
* which databases to create and where they sync to. The core engine
|
* which databases to create and where they sync to. The core engine
|
||||||
* (`PouchDatabaseManager`) has zero knowledge of business domains.
|
* (`PouchDatabaseManager`) has zero knowledge of business domains.
|
||||||
*/
|
*/
|
||||||
|
import { ENV } from '../../environment';
|
||||||
import { PouchDatabaseManager } from '@repo/core-storage';
|
import { PouchDatabaseManager } from '@repo/core-storage';
|
||||||
import { ENV } from '../../environment/env';
|
|
||||||
import type { Item, POSConfiguration } from './types';
|
import { ItemEntity, POSConfigurationEntity } from './entities';
|
||||||
|
|
||||||
// ─── Manager Singleton ──────────────────────────────────────────
|
// ─── Manager Singleton ──────────────────────────────────────────
|
||||||
|
|
||||||
@@ -24,9 +25,7 @@ function buildRemoteUrl(dbName: string): string | undefined {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 1. Tambahkan http:// secara otomatis jika DevOps hanya mengisi IP Address di .env
|
// 1. Tambahkan http:// secara otomatis jika DevOps hanya mengisi IP Address di .env
|
||||||
const safeBaseUrl = COUCHDB_BASE_URL.startsWith('http')
|
const safeBaseUrl = COUCHDB_BASE_URL.startsWith('http') ? COUCHDB_BASE_URL : `http://${COUCHDB_BASE_URL}`;
|
||||||
? COUCHDB_BASE_URL
|
|
||||||
: `http://${COUCHDB_BASE_URL}`;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 2. Gunakan URL parser yang aman dari karakter aneh pada password
|
// 2. Gunakan URL parser yang aman dari karakter aneh pada password
|
||||||
@@ -45,13 +44,13 @@ function buildRemoteUrl(dbName: string): string | undefined {
|
|||||||
// ─── Register Application Databases ─────────────────────────────
|
// ─── Register Application Databases ─────────────────────────────
|
||||||
|
|
||||||
/** POS Configuration database — stores device settings, theme, etc. */
|
/** POS Configuration database — stores device settings, theme, etc. */
|
||||||
export const posConfigDB = dbManager.register<POSConfiguration>({
|
export const posConfigDB = dbManager.register<POSConfigurationEntity>({
|
||||||
localName: 'pos_configuration',
|
localName: 'pos_configuration',
|
||||||
remoteUrl: buildRemoteUrl('pos_configuration'),
|
remoteUrl: buildRemoteUrl('pos_configuration'),
|
||||||
});
|
});
|
||||||
|
|
||||||
/** Items database — products available for sale in POS. */
|
/** Items database — products available for sale in POS. */
|
||||||
export const itemDB = dbManager.register<Item>({
|
export const itemDB = dbManager.register<ItemEntity>({
|
||||||
localName: 'item',
|
localName: 'item',
|
||||||
remoteUrl: buildRemoteUrl('item'),
|
remoteUrl: buildRemoteUrl('item'),
|
||||||
});
|
});
|
||||||
@@ -16,7 +16,7 @@ import './main.css';
|
|||||||
import { lazy, StrictMode } from 'react';
|
import { lazy, StrictMode } from 'react';
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
import { setupI18n } from '@repo/core-i18n';
|
import { setupI18n } from '@repo/core-i18n';
|
||||||
import { secureStorage, AppStorageKey } from './core/storage';
|
import { secureStorage, AppStorageKey } from './core/storage/local';
|
||||||
|
|
||||||
const App = lazy(() => import('./apps'));
|
const App = lazy(() => import('./apps'));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user