refactor: restructure storage and environment modules; remove unused code
- Deleted unused PouchDB configuration and types from core storage. - Removed Electron-related hooks and utilities that are no longer needed. - Introduced new local storage management for application keys. - Created a new environment wrapper for landing application. - Added public HTTP client for landing application with minimal configuration. - Implemented new PouchDB entities for items and POS configurations. - Updated main application entry point to reflect new storage structure.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { CommonRemoteDataServices } 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 ──────────────────────────────────────────────
|
||||
|
||||
@@ -31,10 +31,7 @@ export interface PublicContentEntity extends BaseEntity {
|
||||
* const { data: post } = await publicContentServices.getOne('hello-world');
|
||||
* ```
|
||||
*/
|
||||
export const publicContentServices = new CommonRemoteDataServices<PublicContentEntity>(
|
||||
publicClient,
|
||||
{
|
||||
apiUrl: '/content',
|
||||
moduleKey: 'PUBLIC_CONTENT',
|
||||
},
|
||||
);
|
||||
export const publicContentServices = new CommonRemoteDataServices<PublicContentEntity>(publicClient, {
|
||||
apiUrl: '/content',
|
||||
moduleKey: 'PUBLIC_CONTENT',
|
||||
});
|
||||
|
||||
@@ -2,8 +2,8 @@ import { useEffect, useState } from 'react';
|
||||
import { useTranslation, changeLanguage, i18n } from '@repo/core-i18n';
|
||||
|
||||
// Decentralized locale imports
|
||||
import homeId from '../locales/id/home.json';
|
||||
import homeEn from '../locales/en/home.json';
|
||||
import homeId from '../core/locales/id/home.json';
|
||||
import homeEn from '../core/locales/en/home.json';
|
||||
|
||||
// Bendera penanda statis di level modul (default: false)
|
||||
let isHomeDictLoaded = false;
|
||||
|
||||
Vendored
+1
-1
@@ -7,7 +7,7 @@ import homeEn from '../locales/en/home.json';
|
||||
declare module 'react-i18next' {
|
||||
interface CustomTypeOptions {
|
||||
defaultNS: 'common';
|
||||
resources: typeof coreResources['en'] & {
|
||||
resources: (typeof coreResources)['en'] & {
|
||||
home: typeof homeEn;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useAppEvent } 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 ──────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CommonRemoteDataServices } 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 ──────────────────────────────────────────────
|
||||
|
||||
@@ -34,10 +34,7 @@ export interface BookingEntity extends BaseEntity {
|
||||
* await bookingServices.confirmProcessTransaction('42');
|
||||
* ```
|
||||
*/
|
||||
export const bookingServices = new CommonRemoteDataServices<BookingEntity>(
|
||||
apiClient,
|
||||
{
|
||||
apiUrl: '/bookings',
|
||||
moduleKey: 'BOOKING',
|
||||
},
|
||||
);
|
||||
export const bookingServices = new CommonRemoteDataServices<BookingEntity>(apiClient, {
|
||||
apiUrl: '/bookings',
|
||||
moduleKey: 'BOOKING',
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
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
|
||||
import bookingId from '../locales/id/booking.json';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { secureStorage, secureIndexedDB, AppStorageKey } from '../../../../../../core/storage';
|
||||
import { secureStorage, secureIndexedDB, AppStorageKey } from '../../../../../../core/storage/local';
|
||||
|
||||
// ─── Demo Data ──────────────────────────────────────────────────
|
||||
|
||||
|
||||
@@ -1,20 +1,12 @@
|
||||
import { useEffect, useState, useCallback } from 'react';
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Group,
|
||||
Stack,
|
||||
Title,
|
||||
Text,
|
||||
Table,
|
||||
Badge,
|
||||
} from '@repo/ui/components';
|
||||
import { itemDB, posConfigDB } from '../../core/db';
|
||||
import type { Item, POSConfiguration } from '../../core/db/types';
|
||||
import { Button, Card, Group, Stack, Title, Text, Table, Badge } from '@repo/ui/components';
|
||||
|
||||
import { itemDB, posConfigDB } from '../../core/storage/pouch-db';
|
||||
import type { ItemEntity, POSConfigurationEntity } from '../../core/storage/pouch-db/entities';
|
||||
|
||||
export default function PouchSample() {
|
||||
const [configs, setConfigs] = useState<POSConfiguration[]>([]);
|
||||
const [items, setItems] = useState<Item[]>([]);
|
||||
const [configs, setConfigs] = useState<POSConfigurationEntity[]>([]);
|
||||
const [items, setItems] = useState<ItemEntity[]>([]);
|
||||
|
||||
// Load initial data
|
||||
const loadData = useCallback(async () => {
|
||||
@@ -24,7 +16,7 @@ export default function PouchSample() {
|
||||
|
||||
const allItems = await itemDB.find({ selector: {} });
|
||||
setItems(allItems);
|
||||
console.log({allConfigs, allItems})
|
||||
console.log({ allConfigs, allItems });
|
||||
} catch (err) {
|
||||
console.error('Failed to load PouchDB data', err);
|
||||
}
|
||||
@@ -150,35 +142,35 @@ export default function PouchSample() {
|
||||
<Table.Th className="sticky top-0 bg-white z-10 shadow-sm">Actions</Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
{items.length > 0 ? (
|
||||
items.map((item) => (
|
||||
<Table.Tr key={item._id}>
|
||||
<Table.Td>{item._id}</Table.Td>
|
||||
<Table.Td>{item.name}</Table.Td>
|
||||
<Table.Td>
|
||||
<Badge color="brand" variant="light">
|
||||
{item.item_type}
|
||||
</Badge>
|
||||
</Table.Td>
|
||||
<Table.Td>${Number(item.base_price).toFixed(2)}</Table.Td>
|
||||
<Table.Td>{item.item_rates?.length || 0}</Table.Td>
|
||||
<Table.Td>
|
||||
<Button size="xs" color="error" variant="subtle" onClick={() => handleDeleteItem(item._id)}>
|
||||
Delete
|
||||
</Button>
|
||||
<Table.Tbody>
|
||||
{items.length > 0 ? (
|
||||
items.map((item) => (
|
||||
<Table.Tr key={item._id}>
|
||||
<Table.Td>{item._id}</Table.Td>
|
||||
<Table.Td>{item.name}</Table.Td>
|
||||
<Table.Td>
|
||||
<Badge color="brand" variant="light">
|
||||
{item.item_type}
|
||||
</Badge>
|
||||
</Table.Td>
|
||||
<Table.Td>${Number(item.base_price).toFixed(2)}</Table.Td>
|
||||
<Table.Td>{item.item_rates?.length || 0}</Table.Td>
|
||||
<Table.Td>
|
||||
<Button size="xs" color="error" variant="subtle" onClick={() => handleDeleteItem(item._id)}>
|
||||
Delete
|
||||
</Button>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))
|
||||
) : (
|
||||
<Table.Tr>
|
||||
<Table.Td colSpan={6} align="center">
|
||||
<Text c="dimmed">No items found.</Text>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))
|
||||
) : (
|
||||
<Table.Tr>
|
||||
<Table.Td colSpan={6} align="center">
|
||||
<Text c="dimmed">No items found.</Text>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
)}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
)}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
@@ -202,34 +194,34 @@ export default function PouchSample() {
|
||||
<Table.Th className="sticky top-0 bg-white z-10 shadow-sm">Actions</Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
{configs.length > 0 ? (
|
||||
configs.map((cfg) => (
|
||||
<Table.Tr key={cfg._id}>
|
||||
<Table.Td>{cfg._id}</Table.Td>
|
||||
<Table.Td>{cfg.pos_name}</Table.Td>
|
||||
<Table.Td>{cfg.pos_number}</Table.Td>
|
||||
<Table.Td>
|
||||
<Badge color="info" variant="outline">
|
||||
{cfg.items?.length || 0} Items
|
||||
</Badge>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Button size="xs" color="error" variant="subtle" onClick={() => handleDeleteConfig(cfg._id)}>
|
||||
Delete
|
||||
</Button>
|
||||
<Table.Tbody>
|
||||
{configs.length > 0 ? (
|
||||
configs.map((cfg) => (
|
||||
<Table.Tr key={cfg._id}>
|
||||
<Table.Td>{cfg._id}</Table.Td>
|
||||
<Table.Td>{cfg.pos_name}</Table.Td>
|
||||
<Table.Td>{cfg.pos_number}</Table.Td>
|
||||
<Table.Td>
|
||||
<Badge color="info" variant="outline">
|
||||
{cfg.items?.length || 0} Items
|
||||
</Badge>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Button size="xs" color="error" variant="subtle" onClick={() => handleDeleteConfig(cfg._id)}>
|
||||
Delete
|
||||
</Button>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))
|
||||
) : (
|
||||
<Table.Tr>
|
||||
<Table.Td colSpan={5} align="center">
|
||||
<Text c="dimmed">No configurations found.</Text>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))
|
||||
) : (
|
||||
<Table.Tr>
|
||||
<Table.Td colSpan={5} align="center">
|
||||
<Text c="dimmed">No configurations found.</Text>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
)}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
)}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</div>
|
||||
</Card>
|
||||
</Stack>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// 1. Import hooks yang baru saja dibuat Opus
|
||||
import { Button } from '@repo/ui/components';
|
||||
import { useElectronPrinter } from '../../hooks/use-electron-printer';
|
||||
import { useElectronUpdater } from '../../hooks/use-electron-updater';
|
||||
import { useElectronPrinter } from '../../core/hooks/use-electron-printer';
|
||||
import { useElectronUpdater } from '../../core/hooks/use-electron-updater';
|
||||
|
||||
export default function App() {
|
||||
// 2. Panggil hooks-nya
|
||||
@@ -11,13 +11,15 @@ export default function App() {
|
||||
return (
|
||||
<div style={{ padding: '20px', border: '2px solid blue', margin: '20px' }}>
|
||||
<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}>
|
||||
Refresh Printer
|
||||
</Button>
|
||||
|
||||
|
||||
<h3>🖨️ Daftar Printer di Komputer Ini:</h3>
|
||||
<ul>
|
||||
{printers.length === 0 ? (
|
||||
@@ -32,4 +34,4 @@ export default function App() {
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
NumberInput,
|
||||
Textarea,
|
||||
Switch,
|
||||
Radio,
|
||||
Table,
|
||||
Badge,
|
||||
Divider,
|
||||
@@ -48,13 +47,20 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
||||
|
||||
const getSubtitle = () => {
|
||||
switch (activeTab) {
|
||||
case 'rbac': return 'Role-Based Access Control and Permissions';
|
||||
case 'storage': return 'Offline-First PouchDB Synchronization';
|
||||
case 'auth': return 'Authentication & Security Layers';
|
||||
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';
|
||||
case 'rbac':
|
||||
return 'Role-Based Access Control and Permissions';
|
||||
case 'storage':
|
||||
return 'Offline-First PouchDB Synchronization';
|
||||
case 'auth':
|
||||
return 'Authentication & Security Layers';
|
||||
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';
|
||||
}
|
||||
};
|
||||
|
||||
@@ -70,11 +76,11 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
||||
className="h-screen"
|
||||
styles={{
|
||||
root: { display: 'flex', height: '100vh', overflow: 'hidden' },
|
||||
list: {
|
||||
minWidth: 260,
|
||||
padding: '1rem',
|
||||
borderRight: '1px solid var(--mantine-color-default-border)',
|
||||
backgroundColor: 'var(--mantine-color-default-element-bg)'
|
||||
list: {
|
||||
minWidth: 260,
|
||||
padding: '1rem',
|
||||
borderRight: '1px solid var(--mantine-color-default-border)',
|
||||
backgroundColor: 'var(--mantine-color-default-element-bg)',
|
||||
},
|
||||
panel: { flex: 1, display: 'flex', flexDirection: 'column', height: '100vh', overflow: 'hidden' },
|
||||
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>
|
||||
<Box mb="xl" px="sm">
|
||||
<Title order={3} c="brand.7">Eigen ERP</Title>
|
||||
<Text size="xs" c="dimmed">Architecture Showcase</Text>
|
||||
<Title order={3} c="brand.7">
|
||||
Eigen ERP
|
||||
</Title>
|
||||
<Text size="xs" c="dimmed">
|
||||
Architecture Showcase
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<Tabs.Tab value="ui-components" leftSection={<Layout size={18} />}>
|
||||
@@ -109,22 +119,24 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
||||
|
||||
<Tabs.Panel value={activeTab as string}>
|
||||
{/* Header */}
|
||||
<Paper
|
||||
p="md"
|
||||
radius={0}
|
||||
withBorder
|
||||
style={{
|
||||
borderTop: 0,
|
||||
borderLeft: 0,
|
||||
<Paper
|
||||
p="md"
|
||||
radius={0}
|
||||
withBorder
|
||||
style={{
|
||||
borderTop: 0,
|
||||
borderLeft: 0,
|
||||
borderRight: 0,
|
||||
zIndex: 10,
|
||||
flexShrink: 0
|
||||
zIndex: 10,
|
||||
flexShrink: 0,
|
||||
}}
|
||||
>
|
||||
<Group justify="space-between">
|
||||
<Stack gap={0}>
|
||||
<Title order={3}>Architecture Showcase</Title>
|
||||
<Text size="sm" c="dimmed">{getSubtitle()}</Text>
|
||||
<Text size="sm" c="dimmed">
|
||||
{getSubtitle()}
|
||||
</Text>
|
||||
</Stack>
|
||||
</Group>
|
||||
</Paper>
|
||||
@@ -132,25 +144,32 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
||||
{/* Scrollable Content Area */}
|
||||
<Box className="flex-1 overflow-y-auto p-6" style={{ height: 'calc(100vh - 80px)' }}>
|
||||
<Container size="xl" m={0} p={0}>
|
||||
|
||||
{/* --- UI COMPONENTS TAB --- */}
|
||||
{activeTab === 'ui-components' && (
|
||||
<Stack gap="xl">
|
||||
{/* Control Panel */}
|
||||
<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">
|
||||
<Select
|
||||
label="Color Scheme"
|
||||
value={colorScheme}
|
||||
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
|
||||
label="Density (Spacing & Sizing)"
|
||||
value={density}
|
||||
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>
|
||||
</Card>
|
||||
@@ -159,22 +178,40 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
||||
<Card withBorder shadow="sm" radius="md" p="md">
|
||||
<Stack gap="lg">
|
||||
<div>
|
||||
<Title order={4} mb="xs">Typography & Badges</Title>
|
||||
<Text size="sm" c="dimmed">This is dimmed small text indicating a subtitle.</Text>
|
||||
<Title order={4} mb="xs">
|
||||
Typography & Badges
|
||||
</Title>
|
||||
<Text size="sm" c="dimmed">
|
||||
This is dimmed small text indicating a subtitle.
|
||||
</Text>
|
||||
<Group mt="md">
|
||||
<Badge color="brand">Brand Badge</Badge>
|
||||
<Badge color="success" variant="light">Success Status</Badge>
|
||||
<Badge color="error" variant="outline">Error State</Badge>
|
||||
<Badge color="success" variant="light">
|
||||
Success Status
|
||||
</Badge>
|
||||
<Badge color="error" variant="outline">
|
||||
Error State
|
||||
</Badge>
|
||||
</Group>
|
||||
</div>
|
||||
<Divider />
|
||||
<div>
|
||||
<Title order={4} mb="md">Buttons</Title>
|
||||
<Title order={4} mb="md">
|
||||
Buttons
|
||||
</Title>
|
||||
<Group>
|
||||
<Button variant="filled" color="brand">Filled Button</Button>
|
||||
<Button variant="outline" color="brand">Outline Button</Button>
|
||||
<Button variant="light" color="info">Light Info</Button>
|
||||
<Button variant="subtle" color="error">Cancel</Button>
|
||||
<Button variant="filled" color="brand">
|
||||
Filled Button
|
||||
</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>
|
||||
</div>
|
||||
</Stack>
|
||||
@@ -182,7 +219,9 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
||||
|
||||
{/* Forms */}
|
||||
<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">
|
||||
<Group grow align="flex-start">
|
||||
<TextInput label="First Name" placeholder="Enter your first name" withAsterisk />
|
||||
@@ -202,7 +241,9 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
||||
|
||||
{/* Data Grid */}
|
||||
<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.Thead>
|
||||
<Table.Tr>
|
||||
@@ -218,7 +259,12 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
||||
<Table.Td>{row.id}</Table.Td>
|
||||
<Table.Td>{row.customer}</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}
|
||||
</Badge>
|
||||
</Table.Td>
|
||||
@@ -242,7 +288,9 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
||||
{activeTab === 'rbac' && (
|
||||
<Stack gap="xl">
|
||||
<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>
|
||||
</Card>
|
||||
</Stack>
|
||||
@@ -252,7 +300,9 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
||||
{activeTab === 'auth' && (
|
||||
<Stack gap="xl">
|
||||
<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>
|
||||
</Card>
|
||||
</Stack>
|
||||
@@ -262,7 +312,9 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
||||
{activeTab === 'events' && (
|
||||
<Stack gap="xl">
|
||||
<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>
|
||||
<ExamplePage />
|
||||
</Card>
|
||||
@@ -280,7 +332,6 @@ export default function ShowcaseView({ colorScheme, setColorScheme, density, set
|
||||
</Card>
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
</Container>
|
||||
</Box>
|
||||
</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
|
||||
* (`PouchDatabaseManager`) has zero knowledge of business domains.
|
||||
*/
|
||||
import { ENV } from '../../environment';
|
||||
import { PouchDatabaseManager } from '@repo/core-storage';
|
||||
import { ENV } from '../../environment/env';
|
||||
import type { Item, POSConfiguration } from './types';
|
||||
|
||||
import { ItemEntity, POSConfigurationEntity } from './entities';
|
||||
|
||||
// ─── 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
|
||||
const safeBaseUrl = COUCHDB_BASE_URL.startsWith('http')
|
||||
? COUCHDB_BASE_URL
|
||||
: `http://${COUCHDB_BASE_URL}`;
|
||||
const safeBaseUrl = COUCHDB_BASE_URL.startsWith('http') ? COUCHDB_BASE_URL : `http://${COUCHDB_BASE_URL}`;
|
||||
|
||||
try {
|
||||
// 2. Gunakan URL parser yang aman dari karakter aneh pada password
|
||||
@@ -45,13 +44,13 @@ function buildRemoteUrl(dbName: string): string | undefined {
|
||||
// ─── Register Application Databases ─────────────────────────────
|
||||
|
||||
/** POS Configuration database — stores device settings, theme, etc. */
|
||||
export const posConfigDB = dbManager.register<POSConfiguration>({
|
||||
export const posConfigDB = dbManager.register<POSConfigurationEntity>({
|
||||
localName: 'pos_configuration',
|
||||
remoteUrl: buildRemoteUrl('pos_configuration'),
|
||||
});
|
||||
|
||||
/** Items database — products available for sale in POS. */
|
||||
export const itemDB = dbManager.register<Item>({
|
||||
export const itemDB = dbManager.register<ItemEntity>({
|
||||
localName: 'item',
|
||||
remoteUrl: buildRemoteUrl('item'),
|
||||
});
|
||||
@@ -16,7 +16,7 @@ import './main.css';
|
||||
import { lazy, StrictMode } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { setupI18n } from '@repo/core-i18n';
|
||||
import { secureStorage, AppStorageKey } from './core/storage';
|
||||
import { secureStorage, AppStorageKey } from './core/storage/local';
|
||||
|
||||
const App = lazy(() => import('./apps'));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user