Merge branch 'main' of https://git.eigen.co.id/eigen/fe-monorepo-template into core/page-provider
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
import { useEffect, useState, useCallback } from 'react';
|
||||
import { Button, Card, Group, Stack, Title, Text, Table, Badge } from '@repo/ui/components';
|
||||
|
||||
import { itemDB, posConfigDB } from '../../core/storage/pouch-db';
|
||||
import { itemDB, posConfigDB, newItemDB } from '../../core/storage/pouch-db';
|
||||
import type { ItemEntity, POSConfigurationEntity } from '../../core/storage/pouch-db/entities';
|
||||
|
||||
export default function PouchSample() {
|
||||
const [configs, setConfigs] = useState<POSConfigurationEntity[]>([]);
|
||||
const [items, setItems] = useState<ItemEntity[]>([]);
|
||||
const [newItems, setNewItems] = useState<ItemEntity[]>([]);
|
||||
|
||||
// Load initial data
|
||||
const loadData = useCallback(async () => {
|
||||
@@ -16,7 +17,13 @@ export default function PouchSample() {
|
||||
|
||||
const allItems = await itemDB.find({ selector: {} });
|
||||
setItems(allItems);
|
||||
console.log({ allConfigs, allItems });
|
||||
|
||||
// We can use getAll() or find() on Envelope DB. It's automatically scoped.
|
||||
const allNewItems = await newItemDB.getAll();
|
||||
console.log('allNewItems', allNewItems);
|
||||
setNewItems(allNewItems as ItemEntity[]);
|
||||
|
||||
console.log({ allConfigs, allItems, allNewItems });
|
||||
} catch (err) {
|
||||
console.error('Failed to load PouchDB data', err);
|
||||
}
|
||||
@@ -35,10 +42,15 @@ export default function PouchSample() {
|
||||
loadData();
|
||||
});
|
||||
|
||||
const unsubscribeNewItems = newItemDB.onChange(() => {
|
||||
loadData();
|
||||
});
|
||||
|
||||
// 3. CRITICAL: Cleanup to prevent memory leaks on unmount
|
||||
return () => {
|
||||
unsubscribeItems();
|
||||
unsubscribePos();
|
||||
unsubscribeNewItems();
|
||||
};
|
||||
}, [loadData]);
|
||||
|
||||
@@ -102,10 +114,40 @@ export default function PouchSample() {
|
||||
}
|
||||
};
|
||||
|
||||
// ─── New Items Envelope Handlers ────────────────────────────────
|
||||
|
||||
const handleAddNewItem = async () => {
|
||||
try {
|
||||
const id = `new-item-${Date.now()}`;
|
||||
await newItemDB.create({
|
||||
_id: id,
|
||||
name: 'ENVELOPE ITEM TEST',
|
||||
base_price: '100000',
|
||||
item_type: 'souvenir',
|
||||
usage_type: 'retail',
|
||||
item_category: [{ name: 'Merchandise' }],
|
||||
});
|
||||
|
||||
loadData();
|
||||
} catch (err) {
|
||||
console.error('Failed to add new item', err);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteNewItem = async (id: string) => {
|
||||
try {
|
||||
await newItemDB.delete(id);
|
||||
loadData();
|
||||
} catch (err) {
|
||||
console.error('Failed to delete new item', err);
|
||||
}
|
||||
};
|
||||
|
||||
const handleClearAll = async () => {
|
||||
try {
|
||||
await posConfigDB.cleanAllData();
|
||||
await itemDB.cleanAllData();
|
||||
await newItemDB.cleanAllData();
|
||||
loadData();
|
||||
} catch (err) {
|
||||
console.error('Failed to clear data', err);
|
||||
@@ -124,7 +166,7 @@ export default function PouchSample() {
|
||||
{/* Items Inventory Table */}
|
||||
<Card withBorder shadow="sm" radius="md" p="md">
|
||||
<Group justify="space-between" mb="md">
|
||||
<Title order={4}>Items Database</Title>
|
||||
<Title order={4}>Items Database (Standard)</Title>
|
||||
<Button onClick={handleAddItem} color="success">
|
||||
Inject Mock ERP Item
|
||||
</Button>
|
||||
@@ -174,6 +216,59 @@ export default function PouchSample() {
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* New Items Envelope Table */}
|
||||
<Card withBorder shadow="sm" radius="md" p="md">
|
||||
<Group justify="space-between" mb="md">
|
||||
<Title order={4}>New Items Database (Envelope Pattern)</Title>
|
||||
<Button onClick={handleAddNewItem} color="brand">
|
||||
Inject Mock Envelope Item
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
<div className="max-h-[400px] overflow-y-auto border border-gray-200 rounded-lg scrollbar-thin scrollbar-thumb-gray-300">
|
||||
<Table striped highlightOnHover withTableBorder withColumnBorders>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
<Table.Th className="sticky top-0 bg-white z-10 shadow-sm">ID</Table.Th>
|
||||
<Table.Th className="sticky top-0 bg-white z-10 shadow-sm">Name</Table.Th>
|
||||
<Table.Th className="sticky top-0 bg-white z-10 shadow-sm">Type</Table.Th>
|
||||
<Table.Th className="sticky top-0 bg-white z-10 shadow-sm">Base Price</Table.Th>
|
||||
<Table.Th className="sticky top-0 bg-white z-10 shadow-sm">Rates Count</Table.Th>
|
||||
<Table.Th className="sticky top-0 bg-white z-10 shadow-sm">Actions</Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
{newItems.length > 0 ? (
|
||||
newItems.map((item) => (
|
||||
<Table.Tr key={item._id}>
|
||||
<Table.Td>{item._id}</Table.Td>
|
||||
<Table.Td>{item.name}</Table.Td>
|
||||
<Table.Td>
|
||||
<Badge color="violet" 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={() => handleDeleteNewItem(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.Tbody>
|
||||
</Table>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* POS Configuration Table */}
|
||||
<Card withBorder shadow="sm" radius="md" p="md">
|
||||
<Group justify="space-between" mb="md">
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './item.pouchdb.entity';
|
||||
export * from './pos-configuration.pouchdb.entity';
|
||||
export * from './new-item.pouchdb.entity';
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
export interface SeasonType {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface SeasonPeriod {
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
season_type: SeasonType;
|
||||
}
|
||||
|
||||
export interface ItemRate {
|
||||
id: string;
|
||||
price: string;
|
||||
season_period: SeasonPeriod;
|
||||
}
|
||||
|
||||
export interface ItemCategory {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detailed interface for an Item entity, based on the provided JSON sample.
|
||||
* This represents the business data payload (`data` property in the envelope).
|
||||
*/
|
||||
export interface NewItemData {
|
||||
id: string;
|
||||
creator_id: string;
|
||||
creator_name: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
status: 'active' | 'inactive' | string;
|
||||
item_type: string;
|
||||
hpp: string;
|
||||
sales_margin: string;
|
||||
share_profit: string;
|
||||
total_price: number;
|
||||
base_price: string;
|
||||
play_estimation: number;
|
||||
use_queue: boolean;
|
||||
show_to_booking: boolean;
|
||||
breakdown_bundling: boolean;
|
||||
limit_type: string;
|
||||
limit_value: number;
|
||||
item_category_id: string;
|
||||
item_category: ItemCategory;
|
||||
item_rates: ItemRate[];
|
||||
price: string;
|
||||
qty: number;
|
||||
name: string;
|
||||
}
|
||||
@@ -3,16 +3,17 @@
|
||||
*
|
||||
* This module demonstrates the IoC pattern: the consuming app decides
|
||||
* which databases to create and where they sync to. The core engine
|
||||
* (`PouchDatabaseManager`) has zero knowledge of business domains.
|
||||
* (`PouchDBManager` and `PouchEnvelopeManager`) has zero knowledge of business domains.
|
||||
*/
|
||||
import { ENV } from '../../environment';
|
||||
import { PouchDatabaseManager } from '@repo/core-storage';
|
||||
import { PouchDBManager, PouchEnvelopeDBManager } from '@repo/core-storage';
|
||||
|
||||
import { ItemEntity, POSConfigurationEntity } from './entities';
|
||||
|
||||
// ─── Manager Singleton ──────────────────────────────────────────
|
||||
// ─── Manager Singletons ──────────────────────────────────────────
|
||||
|
||||
export const dbManager = new PouchDatabaseManager();
|
||||
export const dbManager = new PouchDBManager();
|
||||
export const envelopeDbManager = new PouchEnvelopeDBManager();
|
||||
|
||||
// ─── Helper: Build Secure Remote URL ────────────────────────────
|
||||
|
||||
@@ -54,3 +55,12 @@ export const itemDB = dbManager.register<ItemEntity>({
|
||||
localName: 'item',
|
||||
remoteUrl: buildRemoteUrl('item'),
|
||||
});
|
||||
|
||||
/** New Items database using the Envelope Service pattern. */
|
||||
export const newItemDB = envelopeDbManager.register(
|
||||
{
|
||||
localName: 'master_data',
|
||||
remoteUrl: buildRemoteUrl('master_data'),
|
||||
},
|
||||
'item',
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user