From dea13acd2be213c8e6cb9540973f3af96048a7d4 Mon Sep 17 00:00:00 2001 From: Bhanu Prakash Sai Potteri Date: Tue, 2 Jun 2026 19:40:15 +0530 Subject: [PATCH] =?UTF-8?q?initial=20commit:=20p2p-dev=20=E2=80=94=20custo?= =?UTF-8?q?m=20frontend=20wired=20to=20dev=20env=20(app=20169)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 6 + frontgen_projects_dev_to_studio.sql | 36 + index.html | 16 + migration_dev_to_studio.sql | 405 ++++ p2p_demo_schema.sql | 164 ++ package-lock.json | 2745 +++++++++++++++++++++++++++ package.json | 29 + postcss.config.js | 6 + public/favicon.ico | Bin 0 -> 3870 bytes public/zino-logo.svg | 9 + public/zino.svg | 9 + seed.sql | 47 + src/App.tsx | 37 + src/api/viewService.ts | 422 ++++ src/components/AppShell.tsx | 302 +++ src/components/DashboardStats.tsx | 84 + src/components/DetailViewPanel.tsx | 363 ++++ src/components/DynamicHeader.tsx | 251 +++ src/components/FormModal.tsx | 257 +++ src/components/ProtectedRoute.tsx | 13 + src/components/RecordViewTable.tsx | 498 +++++ src/components/ScreenRenderer.tsx | 82 + src/components/Skeleton.tsx | 73 + src/config.ts | 74 + src/hooks/AuthContext.tsx | 19 + src/hooks/ThemeContext.tsx | 41 + src/hooks/useAuth.ts | 100 + src/index.css | 47 + src/main.tsx | 24 + src/pages/Home.tsx | 30 + src/pages/Login.tsx | 152 ++ src/vite-env.d.ts | 1 + src/zino-sdk/DynamicForm.tsx | 175 ++ src/zino-sdk/auth.ts | 64 + src/zino-sdk/client.ts | 86 + src/zino-sdk/index.ts | 61 + src/zino-sdk/mock.ts | 243 +++ src/zino-sdk/provider.tsx | 143 ++ src/zino-sdk/types.ts | 285 +++ src/zino-sdk/views.ts | 197 ++ src/zino-sdk/workflow.ts | 223 +++ tailwind.config.js | 13 + tsconfig.app.json | 19 + tsconfig.json | 7 + tsconfig.node.json | 15 + vite.config.ts | 33 + 46 files changed, 7906 insertions(+) create mode 100644 .gitignore create mode 100644 frontgen_projects_dev_to_studio.sql create mode 100644 index.html create mode 100644 migration_dev_to_studio.sql create mode 100644 p2p_demo_schema.sql create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 postcss.config.js create mode 100644 public/favicon.ico create mode 100644 public/zino-logo.svg create mode 100644 public/zino.svg create mode 100644 seed.sql create mode 100644 src/App.tsx create mode 100644 src/api/viewService.ts create mode 100644 src/components/AppShell.tsx create mode 100644 src/components/DashboardStats.tsx create mode 100644 src/components/DetailViewPanel.tsx create mode 100644 src/components/DynamicHeader.tsx create mode 100644 src/components/FormModal.tsx create mode 100644 src/components/ProtectedRoute.tsx create mode 100644 src/components/RecordViewTable.tsx create mode 100644 src/components/ScreenRenderer.tsx create mode 100644 src/components/Skeleton.tsx create mode 100644 src/config.ts create mode 100644 src/hooks/AuthContext.tsx create mode 100644 src/hooks/ThemeContext.tsx create mode 100644 src/hooks/useAuth.ts create mode 100644 src/index.css create mode 100644 src/main.tsx create mode 100644 src/pages/Home.tsx create mode 100644 src/pages/Login.tsx create mode 100644 src/vite-env.d.ts create mode 100644 src/zino-sdk/DynamicForm.tsx create mode 100644 src/zino-sdk/auth.ts create mode 100644 src/zino-sdk/client.ts create mode 100644 src/zino-sdk/index.ts create mode 100644 src/zino-sdk/mock.ts create mode 100644 src/zino-sdk/provider.tsx create mode 100644 src/zino-sdk/types.ts create mode 100644 src/zino-sdk/views.ts create mode 100644 src/zino-sdk/workflow.ts create mode 100644 tailwind.config.js create mode 100644 tsconfig.app.json create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json create mode 100644 vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c58db5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +dist/ +.env +*.local +.DS_Store +*-local-command-caveatcaveat-*.txt diff --git a/frontgen_projects_dev_to_studio.sql b/frontgen_projects_dev_to_studio.sql new file mode 100644 index 0000000..642e2b3 --- /dev/null +++ b/frontgen_projects_dev_to_studio.sql @@ -0,0 +1,36 @@ +-- ============================================================ +-- Frontgen Projects — Dev → Studio Migration +-- Run against: studio DB +-- +-- Studio already has: clinic-workflow, support-ticket, customer-onboarding, +-- task-management, truck, p2p (already on studio URL) +-- Missing in studio: dealer-1, grfm-app, dealer-new-1, grfm, truck2, adani-dealer +-- ============================================================ + +BEGIN; + +-- 1. Repoint zino_api_url for projects already in studio (excluding p2p which is correct) +UPDATE frontgen.projects +SET zino_api_url = 'https://studio.getzino.in' +WHERE id IN ( + '09c3357e-9b6c-4a93-abaf-9464e90ebbe4', -- Clinic workflow + '14307640-8e37-4448-ba3c-c3672da68bbf', -- Support Ticket + 'a22cd6ba-c5e4-4f7e-ac84-1db17559c075', -- Customer Onboarding + '242eb4da-066f-4c46-9f5b-479f3e1df3f1', -- Task Management + '9134befe-f74b-4c87-925d-d4eaa096dbf0' -- Truck +); + +-- 2. Insert the 6 missing projects (all pre-pointed at studio) +INSERT INTO frontgen.projects (id, name, slug, framework, repo_name, preview_url, workflow_id, zino_api_url, last_build_status, last_build_at, last_commit_sha, created_at, updated_at) VALUES +('0afe0940-6ced-4310-bd95-acbda3d9da6e', 'dealer 1', 'dealer-1', 'react', 'dealer-1', 'https://preview.getzino.in/dealer-1/', 'fd7e72a5-5920-4d41-a660-40aa14a21fb6', 'https://studio.getzino.in', 'success', '2026-04-02 10:17:20.206652+00', '1bdd529a7bb461dee4ffc33c8c75dd7795f710a6', '2026-03-31 07:01:58.61003+00', '2026-04-02 10:17:20.209667+00'), +('0ca7e50c-ea3c-4238-9ae1-07cdd61c9023', 'GRFM APP', 'grfm-app', 'react', 'grfm-app', 'http://preview.getzino.in/grfm-app/', '7dabcd26-30a4-498c-82a8-0fc88f1ad0dc', 'https://studio.getzino.in', 'success', '2026-03-31 10:24:14.231953+00', '5b4c587976d2ba4ba5a8c3bc03617ee9e52c63a2', '2026-03-31 10:06:47.566653+00', '2026-03-31 10:24:14.23535+00'), +('69aa6f58-0e45-4562-8413-19de03f9f8b5', 'Dealer new 1', 'dealer-new-1', 'react', 'dealer-new-1', 'http://preview.getzino.in/dealer-new-1/', '817a45fe-882f-4502-b3cb-4ace65ca7b48', 'https://studio.getzino.in', 'success', '2026-04-10 13:30:05.24563+00', '9369958d64c266ef2c03afeab0c99117a7981388', '2026-04-08 05:58:17.232322+00', '2026-04-10 13:30:05.24978+00'), +('8660fc96-9a06-4813-956f-2a22c8a6c69f', 'GRFM', 'grfm', 'react', 'grfm', 'http://preview.getzino.in/grfm/', '276d050c-c668-4fb4-9d4c-c627fc71c217', 'https://studio.getzino.in', 'success', '2026-04-13 06:15:35.019749+00', 'f9917e10eb4534ecff57bf743393676d8c844b0e', '2026-04-13 06:00:26.479567+00', '2026-04-13 06:15:35.024828+00'), +('a12e234c-be37-4eb8-8410-0bff989e9b0b', 'Truck2', 'truck2', 'react', 'truck2', 'http://preview.getzino.in/truck2/', '6e144d23-dd76-478c-b330-6acd3b736129"', 'https://studio.getzino.in', 'success', '2026-04-13 11:56:50.316279+00', '9014d4522664b12315fae11f516632c20ada1617', '2026-04-13 11:31:17.284247+00', '2026-04-13 11:56:50.320774+00'), +('0782a310-8dbc-4032-93b4-98454ae33317', 'Adani Dealer', 'adani-dealer', 'react', 'adani-dealer', 'http://preview.getzino.in/adani-dealer/', 'fc0dc1f1-bf24-4e5b-a066-6d16efc95899', 'https://studio.getzino.in', 'success', '2026-04-16 05:57:06.831479+00', '22025ea5fe2a28df6cb954de9141edeb3d68ead0', '2026-04-16 05:40:06.970758+00', '2026-04-16 05:57:06.834982+00') +ON CONFLICT (id) DO NOTHING; + +COMMIT; + +-- Verify +SELECT id, name, slug, zino_api_url FROM frontgen.projects ORDER BY created_at; diff --git a/index.html b/index.html new file mode 100644 index 0000000..f1ad924 --- /dev/null +++ b/index.html @@ -0,0 +1,16 @@ + + + + + + + + + + P2P + + +
+ + + \ No newline at end of file diff --git a/migration_dev_to_studio.sql b/migration_dev_to_studio.sql new file mode 100644 index 0000000..ee28685 --- /dev/null +++ b/migration_dev_to_studio.sql @@ -0,0 +1,405 @@ +-- ============================================================ +-- P2P Invoice System — Full Migration: Dev → Studio +-- Org 20, App 20 +-- Generated from dev DB (studio-v2-pg) +-- ============================================================ +BEGIN; + +-- 1. Users + +INSERT INTO usersystem.tbl_users (id, name, email, password) VALUES (29100, 'Priya AI Finance (P2P Demo)', 'org20_priya.p2p@company.com', 'priya123') ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_users (id, name, email, password) VALUES (29101, 'Vendor Portal User', 'org20_vendor@abcsupplies.com', 'vendor123') ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_users (id, name, email, password) VALUES (29102, 'Rajesh Sharma (Warehouse)', 'org20_rajesh.warehouse@company.com', 'rajesh123') ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_users (id, name, email, password) VALUES (29103, 'Meera Patel (Procurement)', 'org20_meera.procurement@company.com', 'meera123') ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_users (id, name, email, password) VALUES (29104, 'Anita Desai (Accounts Payable)', 'org20_anita.ap@company.com', 'anita123') ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_users (id, name, email, password) VALUES (29105, 'Vikram Singh (Finance Manager)', 'org20_vikram.finance@company.com', 'vikram123') ON CONFLICT (id) DO NOTHING; + +-- Org users +INSERT INTO usersystem.tbl_org_users (id, user_id, org_id) VALUES (20027, 29100, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_org_users (id, user_id, org_id) VALUES (20028, 29101, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_org_users (id, user_id, org_id) VALUES (20029, 29102, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_org_users (id, user_id, org_id) VALUES (20030, 29103, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_org_users (id, user_id, org_id) VALUES (20031, 29104, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_org_users (id, user_id, org_id) VALUES (20032, 29105, 20) ON CONFLICT (id) DO NOTHING; + +-- Roles +INSERT INTO usersystem.tbl_roles (id, name, org_id) VALUES (29100, 'p2p_ai_finance', 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_roles (id, name, org_id) VALUES (29101, 'p2p_vendor', 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_roles (id, name, org_id) VALUES (29102, 'p2p_warehouse', 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_roles (id, name, org_id) VALUES (29103, 'p2p_procurement', 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_roles (id, name, org_id) VALUES (29104, 'p2p_ap_team', 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_roles (id, name, org_id) VALUES (29105, 'p2p_finance_reviewer', 20) ON CONFLICT (id) DO NOTHING; + +-- User roles +INSERT INTO usersystem.tbl_user_roles (user_id, role_id, org_id) VALUES (29100, 29100, 20) ON CONFLICT DO NOTHING; +INSERT INTO usersystem.tbl_user_roles (user_id, role_id, org_id) VALUES (29101, 29101, 20) ON CONFLICT DO NOTHING; +INSERT INTO usersystem.tbl_user_roles (user_id, role_id, org_id) VALUES (29102, 29102, 20) ON CONFLICT DO NOTHING; +INSERT INTO usersystem.tbl_user_roles (user_id, role_id, org_id) VALUES (29103, 29103, 20) ON CONFLICT DO NOTHING; +INSERT INTO usersystem.tbl_user_roles (user_id, role_id, org_id) VALUES (29104, 29104, 20) ON CONFLICT DO NOTHING; +INSERT INTO usersystem.tbl_user_roles (user_id, role_id, org_id) VALUES (29105, 29105, 20) ON CONFLICT DO NOTHING; + +-- User groups + +-- User app assignments +INSERT INTO usersystem.tbl_org_user_apps (id, org_user_id, app_id, org_id) VALUES (20129, 20027, 20, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_org_user_apps (id, org_user_id, app_id, org_id) VALUES (20130, 20028, 20, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_org_user_apps (id, org_user_id, app_id, org_id) VALUES (20131, 20029, 20, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_org_user_apps (id, org_user_id, app_id, org_id) VALUES (20132, 20030, 20, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_org_user_apps (id, org_user_id, app_id, org_id) VALUES (20133, 20031, 20, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO usersystem.tbl_org_user_apps (id, org_user_id, app_id, org_id) VALUES (20134, 20032, 20, 20) ON CONFLICT (id) DO NOTHING; + +-- 2. App +INSERT INTO tbl_apps (id, name, org_id, description) VALUES (20, 'P2P Invoice System', 20, 'AI-powered invoice validation with department clarification and finance approval') ON CONFLICT (id) DO NOTHING; + +-- Workflow config +INSERT INTO tbl_appconfig_workflows (id, workflow_uid, version, app_id, content) VALUES (20109, 'wf_p2p_invoice_demo', '1', 20, '{"name": "P2P Invoice Validation", "states": [{"uid": "p2p-state-awaiting-clarification", "name": "Awaiting Clarification", "type": "STANDARD", "allowed_activities": ["p2p-act-provide-clarification"]}, {"uid": "p2p-state-invoice-submitted", "name": "Invoice Submitted", "type": "STANDARD", "allowed_activities": ["p2p-act-request-clarification", "p2p-act-submit-recommendation"]}, {"uid": "p2p-state-ai-analysis", "name": "AI Analysis", "type": "STANDARD", "allowed_activities": ["p2p-act-request-clarification", "p2p-act-submit-recommendation"]}, {"uid": "p2p-state-finance-review", "name": "Finance Review", "type": "STANDARD", "allowed_activities": ["p2p-act-approve-payment", "p2p-act-reject-payment", "p2p-act-hold-payment"]}, {"uid": "p2p-state-approved", "name": "Approved", "type": "END", "allowed_activities": []}, {"uid": "p2p-state-rejected", "name": "Rejected", "type": "END", "allowed_activities": []}, {"uid": "p2p-state-on-hold", "name": "On Hold", "type": "END", "allowed_activities": []}], "version": 1, "sg_rules": [], "activities": [{"uid": "p2p-act-submit-invoice", "name": "Submit Invoice", "type": "INIT", "ai_confidence_threshold": 0.5}, {"uid": "p2p-act-request-clarification", "name": "Request Clarification", "type": "NORMAL", "ai_confidence_threshold": 0.5}, {"uid": "p2p-act-submit-recommendation", "name": "Submit Recommendation", "type": "NORMAL", "ai_confidence_threshold": 0.5}, {"uid": "p2p-act-provide-clarification", "name": "Provide Clarification", "type": "NORMAL", "ai_confidence_threshold": 0.5}, {"uid": "p2p-act-approve-payment", "name": "Approve Payment", "type": "NORMAL", "ai_confidence_threshold": 0.5}, {"uid": "p2p-act-reject-payment", "name": "Reject Payment", "type": "NORMAL", "ai_confidence_threshold": 0.5}, {"uid": "p2p-act-hold-payment", "name": "Hold Payment", "type": "NORMAL", "ai_confidence_threshold": 0.5}], "stage_gates": [], "transitions": [{"to_state_id": "p2p-state-invoice-submitted", "from_state_id": "", "by_activity_id": "p2p-act-submit-invoice", "transition_type": "INIT_TO_STATE"}, {"to_state_id": "p2p-state-awaiting-clarification", "from_state_id": "p2p-state-invoice-submitted", "by_activity_id": "p2p-act-request-clarification", "transition_type": "TO_STATE"}, {"to_state_id": "p2p-state-finance-review", "from_state_id": "p2p-state-invoice-submitted", "by_activity_id": "p2p-act-submit-recommendation", "transition_type": "TO_STATE"}, {"to_state_id": "p2p-state-awaiting-clarification", "from_state_id": "p2p-state-ai-analysis", "by_activity_id": "p2p-act-request-clarification", "transition_type": "TO_STATE"}, {"to_state_id": "p2p-state-finance-review", "from_state_id": "p2p-state-ai-analysis", "by_activity_id": "p2p-act-submit-recommendation", "transition_type": "TO_STATE"}, {"to_state_id": "p2p-state-ai-analysis", "from_state_id": "p2p-state-awaiting-clarification", "by_activity_id": "p2p-act-provide-clarification", "transition_type": "TO_STATE"}, {"to_state_id": "p2p-state-approved", "from_state_id": "p2p-state-finance-review", "by_activity_id": "p2p-act-approve-payment", "transition_type": "TO_STATE"}, {"to_state_id": "p2p-state-rejected", "from_state_id": "p2p-state-finance-review", "by_activity_id": "p2p-act-reject-payment", "transition_type": "TO_STATE"}, {"to_state_id": "p2p-state-on-hold", "from_state_id": "p2p-state-finance-review", "by_activity_id": "p2p-act-hold-payment", "transition_type": "TO_STATE"}], "workflow_id": "wf_p2p_invoice_demo", "activity_prefills": [], "activity_triggers": [{"nodes": [{"id": "a0a0a0a0-0000-4000-8000-000000093011", "name": "Start", "type": "start", "edges": [{"target": "a0a0a0a0-0000-4000-8000-000000093012", "source_handle": "output"}], "config": {}, "ui_config": null}, {"id": "a0a0a0a0-0000-4000-8000-000000093012", "name": "AI Employee", "type": "aiEmployee", "edges": [{"target": "a0a0a0a0-0000-4000-8000-000000093013", "source_handle": "output"}], "config": {"ai_user_id": "29100"}, "ui_config": null}, {"id": "a0a0a0a0-0000-4000-8000-000000093013", "name": "Complete", "type": "response", "edges": [], "config": {"message": "AI Employee task dispatched", "success": true, "status_code": 200}, "ui_config": null}], "trigger_uid": "trigger_p2p_submit", "activity_uid": "p2p-act-submit-invoice", "trigger_config": {}}, {"nodes": [{"id": "a0a0a0a0-0000-4000-8000-000000093041", "name": "Start", "type": "start", "edges": [{"target": "a0a0a0a0-0000-4000-8000-000000093042", "source_handle": "output"}], "config": {}, "ui_config": null}, {"id": "a0a0a0a0-0000-4000-8000-000000093042", "name": "AI Employee", "type": "aiEmployee", "edges": [{"target": "a0a0a0a0-0000-4000-8000-000000093043", "source_handle": "output"}], "config": {"ai_user_id": "29100"}, "ui_config": null}, {"id": "a0a0a0a0-0000-4000-8000-000000093043", "name": "Complete", "type": "response", "edges": [], "config": {"message": "AI Employee task dispatched", "success": true, "status_code": 200}, "ui_config": null}], "trigger_uid": "trigger_p2p_clarify", "activity_uid": "p2p-act-provide-clarification", "trigger_config": {}}], "activity_data_fields": [{"data_fields": [{"id": "vendor_id", "uid": "p2p-field-9401", "name": "Vendor ID", "type": "local", "data_type": "text", "mandatory": true}, {"id": "vendor_name", "uid": "p2p-field-9402", "name": "Vendor Name", "type": "local", "data_type": "text", "mandatory": true}, {"id": "invoice_number", "uid": "p2p-field-9403", "name": "Invoice Number", "type": "local", "data_type": "text", "mandatory": true}, {"id": "invoice_date", "uid": "p2p-field-9404", "name": "Invoice Date", "type": "local", "data_type": "date", "mandatory": true}, {"id": "po_number", "uid": "p2p-field-9405", "name": "PO Number", "type": "local", "data_type": "text", "mandatory": true}, {"id": "currency", "uid": "p2p-field-9406", "name": "Currency", "type": "local", "data_type": "text", "mandatory": false}, {"id": "total_amount", "uid": "p2p-field-9407", "name": "Total Amount", "type": "local", "data_type": "number", "mandatory": true}, {"id": "tax_amount", "uid": "p2p-field-9408", "name": "Tax Amount", "type": "local", "data_type": "number", "mandatory": false}, {"id": "payment_terms", "uid": "p2p-field-9409", "name": "Payment Terms", "type": "local", "data_type": "text", "mandatory": false}, {"id": "notes", "uid": "p2p-field-9410", "name": "Notes", "type": "local", "data_type": "text", "mandatory": false}], "activity_uid": "p2p-act-submit-invoice", "activity_name": "Submit Invoice"}, {"data_fields": [{"id": "target_department", "uid": "p2p-field-9411", "name": "Target Department", "type": "local", "data_type": "text", "mandatory": true}, {"id": "clarification_question", "uid": "p2p-field-9412", "name": "Question", "type": "local", "data_type": "text", "mandatory": true}, {"id": "clarification_context", "uid": "p2p-field-9413", "name": "Context", "type": "local", "data_type": "text", "mandatory": false}, {"id": "analysis_so_far", "uid": "p2p-field-9414", "name": "Analysis So Far", "type": "local", "data_type": "text", "mandatory": false}], "activity_uid": "p2p-act-request-clarification", "activity_name": "Request Clarification"}, {"data_fields": [{"id": "response_text", "uid": "p2p-field-9415", "name": "Response", "type": "local", "data_type": "text", "mandatory": true}, {"id": "confirmed_quantity", "uid": "p2p-field-9416", "name": "Confirmed Quantity", "type": "local", "data_type": "number", "mandatory": false}, {"id": "response_notes", "uid": "p2p-field-9417", "name": "Additional Notes", "type": "local", "data_type": "text", "mandatory": false}], "activity_uid": "p2p-act-provide-clarification", "activity_name": "Provide Clarification"}, {"data_fields": [{"id": "recommendation", "uid": "p2p-field-9418", "name": "Recommendation", "type": "local", "data_type": "text", "mandatory": true}, {"id": "recommended_amount", "uid": "p2p-field-9419", "name": "Recommended Payment Amount", "type": "local", "data_type": "number", "mandatory": false}, {"id": "match_summary", "uid": "p2p-field-9420", "name": "Match Summary", "type": "local", "data_type": "text", "mandatory": false}, {"id": "ai_reasoning", "uid": "p2p-field-9421", "name": "AI Reasoning", "type": "local", "data_type": "text", "mandatory": false}, {"id": "ai_confidence", "uid": "p2p-field-9422", "name": "AI Confidence", "type": "local", "data_type": "number", "mandatory": false}], "activity_uid": "p2p-act-submit-recommendation", "activity_name": "Submit Recommendation"}, {"data_fields": [{"id": "approved_amount", "uid": "p2p-field-9423", "name": "Approved Amount", "type": "local", "data_type": "number", "mandatory": true}, {"id": "reviewer_notes", "uid": "p2p-field-9424", "name": "Reviewer Notes", "type": "local", "data_type": "text", "mandatory": false}], "activity_uid": "p2p-act-approve-payment", "activity_name": "Approve Payment"}, {"data_fields": [{"id": "rejection_reason", "uid": "p2p-field-9425", "name": "Rejection Reason", "type": "local", "data_type": "text", "mandatory": true}, {"id": "reviewer_notes", "uid": "p2p-field-9426", "name": "Reviewer Notes", "type": "local", "data_type": "text", "mandatory": false}], "activity_uid": "p2p-act-reject-payment", "activity_name": "Reject Payment"}, {"data_fields": [{"id": "hold_reason", "uid": "p2p-field-9427", "name": "Hold Reason", "type": "local", "data_type": "text", "mandatory": true}, {"id": "reviewer_notes", "uid": "p2p-field-9428", "name": "Reviewer Notes", "type": "local", "data_type": "text", "mandatory": false}], "activity_uid": "p2p-act-hold-payment", "activity_name": "Hold Payment"}], "activity_permissions": [], "workflow_data_fields": null}'::jsonb) ON CONFLICT (id) DO UPDATE SET content = EXCLUDED.content; + +-- Record views +INSERT INTO tbl_appconfig_recordview (id, rv_uid, rv_description, workflow_uid, app_id, config) VALUES (20034, 'p2p-rv-all-invoices', 'All invoice instances across all states', 'wf_p2p_invoice_demo', 20, '{"fields": [{"type": "system-global", "data_type": "text", "field_key": "instance_id", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Instance ID"}, {"type": "system-global", "data_type": "text", "field_key": "current_state_name", "field_uid": "", "is_filter": true, "is_search": false, "activity_id": "SYSTEM", "output_label": "Current State"}, {"type": "local", "data_type": "text", "field_key": "vendor_name", "field_uid": "p2p-field-9401", "is_filter": true, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "Vendor"}, {"type": "local", "data_type": "text", "field_key": "invoice_number", "field_uid": "p2p-field-9403", "is_filter": false, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice #"}, {"type": "local", "data_type": "text", "field_key": "po_number", "field_uid": "p2p-field-9405", "is_filter": false, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "PO #"}, {"type": "local", "data_type": "number", "field_key": "total_amount", "field_uid": "p2p-field-9407", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Amount"}, {"type": "system-global", "data_type": "datetime", "field_key": "created_at", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Created"}]}'::jsonb) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_recordview (id, rv_uid, rv_description, workflow_uid, app_id, config) VALUES (20035, 'p2p-rv-pending-clarifications', 'Invoices awaiting department clarification', 'wf_p2p_invoice_demo', 20, '{"fields": [{"type": "system-global", "data_type": "text", "field_key": "instance_id", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Instance ID"}, {"type": "local", "data_type": "text", "field_key": "vendor_name", "field_uid": "p2p-field-9402", "is_filter": false, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "Vendor"}, {"type": "local", "data_type": "text", "field_key": "invoice_number", "field_uid": "p2p-field-9403", "is_filter": false, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice #"}, {"type": "local", "data_type": "number", "field_key": "total_amount", "field_uid": "p2p-field-9407", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Amount"}, {"type": "local", "data_type": "text", "field_key": "target_department", "field_uid": "p2p-field-9411", "is_filter": true, "is_search": false, "activity_id": "p2p-act-request-clarification", "output_label": "Department"}, {"type": "system-global", "data_type": "datetime", "field_key": "created_at", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Created"}], "prefilters": {"logic": "AND", "conditions": [{"value": "Awaiting Clarification", "operator": "equals", "data_type": "text", "field_key": "current_state_name"}]}}'::jsonb) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_recordview (id, rv_uid, rv_description, workflow_uid, app_id, config) VALUES (20037, 'p2p-rv-vendor-invoices', 'Vendor''s submitted invoices with status tracking', 'wf_p2p_invoice_demo', 20, '{"fields": [{"type": "system-global", "data_type": "text", "field_key": "instance_id", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Instance ID"}, {"type": "system-global", "data_type": "text", "field_key": "current_state_name", "field_uid": "", "is_filter": true, "is_search": false, "activity_id": "SYSTEM", "output_label": "Status"}, {"type": "local", "data_type": "text", "field_key": "invoice_number", "field_uid": "p2p-field-9403", "is_filter": false, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice #"}, {"type": "local", "data_type": "text", "field_key": "po_number", "field_uid": "p2p-field-9405", "is_filter": false, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "PO #"}, {"type": "local", "data_type": "number", "field_key": "total_amount", "field_uid": "p2p-field-9407", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Amount"}, {"type": "system-global", "data_type": "datetime", "field_key": "created_at", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Submitted"}]}'::jsonb) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_recordview (id, rv_uid, rv_description, workflow_uid, app_id, config) VALUES (20036, 'p2p-rv-finance-review-queue', 'Invoices ready for finance review with AI recommendations', 'wf_p2p_invoice_demo', 20, '{"fields": [{"type": "local", "data_type": "number", "field_key": "recommended_amount", "field_uid": "p2p-field-9419", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-recommendation", "output_label": "Recommended Amt"}, {"type": "system-global", "data_type": "datetime", "field_key": "created_at", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Created"}, {"type": "system-global", "data_type": "text", "field_key": "instance_id", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Instance ID"}, {"type": "local", "data_type": "text", "field_key": "vendor_name", "field_uid": "p2p-field-9402", "is_filter": false, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "Vendor"}, {"type": "local", "data_type": "text", "field_key": "invoice_number", "field_uid": "p2p-field-9403", "is_filter": false, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice #"}, {"type": "local", "data_type": "number", "field_key": "total_amount", "field_uid": "p2p-field-9407", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Amount"}, {"type": "local", "data_type": "text", "field_key": "recommendation", "field_uid": "p2p-field-9418", "is_filter": true, "is_search": false, "activity_id": "p2p-act-submit-recommendation", "output_label": "AI Recommendation"}], "prefilters": {"logic": "AND", "conditions": [{"value": "Finance Review", "operator": "equals", "data_type": "text", "field_key": "current_state_name"}]}}'::jsonb) ON CONFLICT (id) DO NOTHING; + +-- Detail views +INSERT INTO tbl_appconfig_detailview (id, dv_uid, dv_description, workflow_uid, app_id, config) VALUES (20014, 'p2p-dv-clarification-detail', 'AI question and context for department response', 'wf_p2p_invoice_demo', 20, '{"fields": [{"type": "system-global", "data_type": "text", "field_key": "instance_id", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Instance ID"}, {"type": "local", "data_type": "text", "field_key": "vendor_name", "field_uid": "p2p-field-9402", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Vendor"}, {"type": "local", "data_type": "text", "field_key": "invoice_number", "field_uid": "p2p-field-9403", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice #"}, {"type": "local", "data_type": "text", "field_key": "po_number", "field_uid": "p2p-field-9405", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "PO #"}, {"type": "local", "data_type": "number", "field_key": "total_amount", "field_uid": "p2p-field-9407", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Amount"}, {"type": "local", "data_type": "text", "field_key": "target_department", "field_uid": "p2p-field-9411", "is_filter": false, "is_search": false, "activity_id": "p2p-act-request-clarification", "output_label": "Target Department"}, {"type": "local", "data_type": "text", "field_key": "clarification_question", "field_uid": "p2p-field-9412", "is_filter": false, "is_search": false, "activity_id": "p2p-act-request-clarification", "output_label": "AI Question"}, {"type": "local", "data_type": "text", "field_key": "clarification_context", "field_uid": "p2p-field-9413", "is_filter": false, "is_search": false, "activity_id": "p2p-act-request-clarification", "output_label": "Context"}, {"type": "local", "data_type": "text", "field_key": "analysis_so_far", "field_uid": "p2p-field-9414", "is_filter": false, "is_search": false, "activity_id": "p2p-act-request-clarification", "output_label": "Analysis So Far"}]}'::jsonb) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_detailview (id, dv_uid, dv_description, workflow_uid, app_id, config) VALUES (20015, 'p2p-dv-finance-review-detail', 'AI recommendation with full decision trail for finance reviewer', 'wf_p2p_invoice_demo', 20, '{"fields": [{"type": "system-global", "data_type": "text", "field_key": "instance_id", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Instance ID"}, {"type": "system-global", "data_type": "text", "field_key": "current_state_name", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Status"}, {"type": "local", "data_type": "text", "field_key": "vendor_name", "field_uid": "p2p-field-9402", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Vendor"}, {"type": "local", "data_type": "text", "field_key": "invoice_number", "field_uid": "p2p-field-9403", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice #"}, {"type": "local", "data_type": "text", "field_key": "po_number", "field_uid": "p2p-field-9405", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "PO #"}, {"type": "local", "data_type": "number", "field_key": "total_amount", "field_uid": "p2p-field-9407", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice Amount"}, {"type": "local", "data_type": "number", "field_key": "tax_amount", "field_uid": "p2p-field-9408", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Tax"}, {"type": "local", "data_type": "text", "field_key": "recommendation", "field_uid": "p2p-field-9418", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-recommendation", "output_label": "AI Recommendation"}, {"type": "local", "data_type": "number", "field_key": "recommended_amount", "field_uid": "p2p-field-9419", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-recommendation", "output_label": "Recommended Amount"}, {"type": "local", "data_type": "text", "field_key": "match_summary", "field_uid": "p2p-field-9420", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-recommendation", "output_label": "Match Summary"}, {"type": "local", "data_type": "text", "field_key": "ai_reasoning", "field_uid": "p2p-field-9421", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-recommendation", "output_label": "AI Reasoning"}, {"type": "local", "data_type": "number", "field_key": "ai_confidence", "field_uid": "p2p-field-9422", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-recommendation", "output_label": "AI Confidence"}]}'::jsonb) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_detailview (id, dv_uid, dv_description, workflow_uid, app_id, config) VALUES (20013, 'p2p-dv-invoice-detail', 'Full invoice detail with AI analysis trail', 'wf_p2p_invoice_demo', 20, '{"fields": [{"type": "system-global", "data_type": "text", "field_key": "instance_id", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Instance ID"}, {"type": "system-global", "data_type": "text", "field_key": "current_state_name", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Status"}, {"type": "system-global", "data_type": "datetime", "field_key": "created_at", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Created"}, {"type": "local", "data_type": "text", "field_key": "vendor_id", "field_uid": "p2p-field-9401", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Vendor ID"}, {"type": "local", "data_type": "text", "field_key": "vendor_name", "field_uid": "p2p-field-9402", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Vendor Name"}, {"type": "local", "data_type": "text", "field_key": "invoice_number", "field_uid": "p2p-field-9403", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice Number"}, {"type": "local", "data_type": "date", "field_key": "invoice_date", "field_uid": "p2p-field-9404", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice Date"}, {"type": "local", "data_type": "text", "field_key": "po_number", "field_uid": "p2p-field-9405", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "PO Number"}, {"type": "local", "data_type": "number", "field_key": "total_amount", "field_uid": "p2p-field-9407", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Total Amount"}, {"type": "local", "data_type": "number", "field_key": "tax_amount", "field_uid": "p2p-field-9408", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Tax Amount"}, {"type": "local", "data_type": "text", "field_key": "payment_terms", "field_uid": "p2p-field-9409", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Payment Terms"}, {"type": "local", "data_type": "text", "field_key": "notes", "field_uid": "p2p-field-9410", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Vendor Notes"}]}'::jsonb) ON CONFLICT (id) DO NOTHING; + +-- Screens +INSERT INTO tbl_appconfig_screens (id, source_screen_id, app_id, screen_name, device, description, layout, permissions) VALUES (20010, 29631, 20, 'P2P - My Invoices', 'desktop', 'P2P - My Invoices', '[{"type": "element", "style": {"marginBottom": "16px"}, "config": {"icon": "add", "name": "+ Submit New Invoice", "type": "button", "params": {"workflow_id": "wf_p2p_invoice_demo", "activity_id_init": "p2p-act-submit-invoice"}, "action_end": [{"type": "refresh_page"}], "job_template": "start_state_machine"}, "classes": ["z-btn-primary"]}, {"type": "element", "style": {"width": "100%"}, "config": {"type": "recordsview", "view_id": "29601"}}]'::jsonb, NULL) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_screens (id, source_screen_id, app_id, screen_name, device, description, layout, permissions) VALUES (20011, 29632, 20, 'P2P - Pending Clarifications', 'desktop', 'P2P - Pending Clarifications', '[{"type": "element", "style": {"width": "100%"}, "config": {"type": "recordsview", "view_id": "29602"}}]'::jsonb, NULL) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_screens (id, source_screen_id, app_id, screen_name, device, description, layout, permissions) VALUES (20013, 29634, 20, 'P2P - All Invoices', 'desktop', 'P2P - All Invoices', '[{"type": "element", "style": {"width": "100%"}, "config": {"type": "recordsview", "view_id": "29604"}}]'::jsonb, NULL) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_screens (id, source_screen_id, app_id, screen_name, device, description, layout, permissions) VALUES (20025, 29641, 20, 'P2P - Invoice Detail', 'desktop', 'P2P - Invoice Detail', '[{"type": "element", "style": {"width": "100%", "padding": "16px"}, "config": {"type": "detailsview", "view_id": "29611"}}]'::jsonb, NULL) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_screens (id, source_screen_id, app_id, screen_name, device, description, layout, permissions) VALUES (20026, 29642, 20, 'P2P - Clarification Detail', 'desktop', 'P2P - Clarification Detail', '[{"type": "element", "style": {"width": "100%", "padding": "16px"}, "config": {"type": "detailsview", "view_id": "29612"}}]'::jsonb, NULL) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_screens (id, source_screen_id, app_id, screen_name, device, description, layout, permissions) VALUES (20027, 29643, 20, 'P2P - Finance Review Detail', 'desktop', 'P2P - Finance Review Detail', '[{"type": "element", "style": {"width": "100%", "padding": "16px"}, "config": {"type": "detailsview", "view_id": "29613"}}]'::jsonb, NULL) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_screens (id, source_screen_id, app_id, screen_name, device, description, layout, permissions) VALUES (20012, 29633, 20, 'P2P - Finance Review', 'desktop', 'P2P - Finance Review', '[{"type": "element", "style": {"width": "100%"}, "config": {"type": "recordsview", "view_id": "29603"}}]'::jsonb, NULL) ON CONFLICT (id) DO NOTHING; + +-- RV Screens +INSERT INTO tbl_appconfig_rv_screens (id, source_screen_id, app_id, screen_name, device, description, layout, rv_template_id) VALUES (20001, 29601, 20, 'Vendor - My Invoices', 'desktop', 'Vendor - My Invoices', '[{"type": "element", "style": {}, "config": {"type": "rv_table", "columns": [{"id": "current_state_name", "display": "Status", "key_name": "current_state_name", "data_type": "text"}, {"id": "invoice_number", "display": "Invoice #", "key_name": "invoice_number", "data_type": "text"}, {"id": "po_number", "display": "PO #", "key_name": "po_number", "data_type": "text"}, {"id": "total_amount", "display": "Amount", "key_name": "total_amount", "data_type": "number"}, {"id": "created_at", "display": "Submitted", "key_name": "created_at", "data_type": "datetime"}], "view_id": "29601", "on_row_click": {"screen_id": "29641", "job_template": "navigate_to_screen"}}}]'::jsonb, 29504) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_rv_screens (id, source_screen_id, app_id, screen_name, device, description, layout, rv_template_id) VALUES (20003, 29603, 20, 'Finance - Review Queue', 'desktop', 'Finance - Review Queue', '[{"type": "element", "style": {}, "config": {"type": "rv_table", "columns": [{"id": "vendor_name", "display": "Vendor", "key_name": "vendor_name", "data_type": "text"}, {"id": "invoice_number", "display": "Invoice #", "key_name": "invoice_number", "data_type": "text"}, {"id": "total_amount", "display": "Amount", "key_name": "total_amount", "data_type": "number"}, {"id": "recommendation", "display": "AI Recommendation", "key_name": "recommendation", "data_type": "text"}, {"id": "recommended_amount", "display": "Recommended Amt", "key_name": "recommended_amount", "data_type": "number"}, {"id": "created_at", "display": "Created", "key_name": "created_at", "data_type": "datetime"}], "view_id": "29603", "on_row_click": {"screen_id": "29643", "job_template": "navigate_to_screen"}}}]'::jsonb, 29503) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_rv_screens (id, source_screen_id, app_id, screen_name, device, description, layout, rv_template_id) VALUES (20004, 29604, 20, 'Admin - All Invoices', 'desktop', 'Admin - All Invoices', '[{"type": "element", "style": {}, "config": {"type": "rv_table", "columns": [{"id": "current_state_name", "display": "Status", "key_name": "current_state_name", "data_type": "text"}, {"id": "vendor_name", "display": "Vendor", "key_name": "vendor_name", "data_type": "text"}, {"id": "invoice_number", "display": "Invoice #", "key_name": "invoice_number", "data_type": "text"}, {"id": "po_number", "display": "PO #", "key_name": "po_number", "data_type": "text"}, {"id": "total_amount", "display": "Amount", "key_name": "total_amount", "data_type": "number"}, {"id": "created_at", "display": "Created", "key_name": "created_at", "data_type": "datetime"}], "view_id": "29604", "on_row_click": {"screen_id": "29641", "job_template": "navigate_to_screen"}}}]'::jsonb, 29501) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_rv_screens (id, source_screen_id, app_id, screen_name, device, description, layout, rv_template_id) VALUES (20002, 29602, 20, 'Department - Pending Clarifications', 'desktop', 'Department - Pending Clarifications', '[{"type": "element", "style": {}, "config": {"type": "rv_table", "columns": [{"id": "vendor_name", "display": "Vendor", "key_name": "vendor_name", "data_type": "text"}, {"id": "invoice_number", "display": "Invoice #", "key_name": "invoice_number", "data_type": "text"}, {"id": "total_amount", "display": "Amount", "key_name": "total_amount", "data_type": "number"}, {"id": "target_department", "display": "Department", "key_name": "target_department", "data_type": "text"}, {"id": "created_at", "display": "Created", "key_name": "created_at", "data_type": "datetime"}], "view_id": "29602", "on_row_click": {"screen_id": "29642", "job_template": "navigate_to_screen"}}}]'::jsonb, 29502) ON CONFLICT (id) DO NOTHING; + +-- DV Screens +INSERT INTO tbl_appconfig_dv_screens (id, source_screen_id, app_id, screen_name, device, description, layout, dv_template_id) VALUES (20005, 29612, 20, 'Clarification Detail View', 'desktop', 'Clarification Detail View', '[{"type": "element", "style": {"fontSize": "16px", "marginTop": "20px", "fontWeight": "700", "borderBottom": "1px solid #e2e8f0", "marginBottom": "8px", "paddingBottom": "6px"}, "config": {"name": "Invoice Summary", "type": "label"}, "classes": []}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Vendor", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Vendor", "keyName": "vendor_name"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Invoice Number", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Invoice #", "keyName": "invoice_number"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "PO Number", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "PO #", "keyName": "po_number"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Amount", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Amount", "keyName": "total_amount"}}}, {"type": "element", "style": {"fontSize": "16px", "marginTop": "20px", "fontWeight": "700", "borderBottom": "1px solid #e2e8f0", "marginBottom": "8px", "paddingBottom": "6px"}, "config": {"name": "AI Clarification Request", "type": "label"}, "classes": []}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Target Department", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Department", "keyName": "target_department"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Question from AI", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Question", "keyName": "clarification_question"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Context", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Context", "keyName": "clarification_context"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Analysis So Far", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Analysis", "keyName": "analysis_so_far"}}}, {"type": "element", "style": {"marginTop": "20px"}, "config": {"icon": "reply", "name": "Respond to Clarification", "type": "button", "params": {"activity_id": "p2p-act-provide-clarification", "workflow_id": "wf_p2p_invoice_demo"}, "action_end": [{"type": "refresh_page"}], "job_template": "perform_activity"}, "classes": ["z-btn-primary"]}]'::jsonb, 29512) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_dv_screens (id, source_screen_id, app_id, screen_name, device, description, layout, dv_template_id) VALUES (20004, 29611, 20, 'Invoice Detail View', 'desktop', 'Invoice Detail View', '[{"type": "element", "style": {"fontSize": "16px", "marginTop": "20px", "fontWeight": "700", "borderBottom": "1px solid #e2e8f0", "marginBottom": "8px", "paddingBottom": "6px"}, "config": {"name": "Invoice Details", "type": "label"}, "classes": []}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Status", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Status", "keyName": "current_state_name"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Vendor", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Vendor", "keyName": "vendor_name"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Invoice Number", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Invoice #", "keyName": "invoice_number"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Invoice Date", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Date", "keyName": "invoice_date"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "PO Number", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "PO #", "keyName": "po_number"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Total Amount", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Amount", "keyName": "total_amount"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Tax Amount", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Tax", "keyName": "tax_amount"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Payment Terms", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Terms", "keyName": "payment_terms"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Vendor Notes", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Notes", "keyName": "notes"}}}]'::jsonb, 29511) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_dv_screens (id, source_screen_id, app_id, screen_name, device, description, layout, dv_template_id) VALUES (20006, 29613, 20, 'Finance Review Detail View', 'desktop', 'Finance Review Detail View', '[{"type": "element", "style": {"fontSize": "16px", "marginTop": "20px", "fontWeight": "700", "borderBottom": "1px solid #e2e8f0", "marginBottom": "8px", "paddingBottom": "6px"}, "config": {"name": "Invoice Details", "type": "label"}, "classes": []}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Status", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Status", "keyName": "current_state_name"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Vendor", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Vendor", "keyName": "vendor_name"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Invoice Number", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Invoice #", "keyName": "invoice_number"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "PO Number", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "PO #", "keyName": "po_number"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Invoice Amount", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Amount", "keyName": "total_amount"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Tax", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Tax", "keyName": "tax_amount"}}}, {"type": "element", "style": {"fontSize": "16px", "marginTop": "20px", "fontWeight": "700", "borderBottom": "1px solid #e2e8f0", "marginBottom": "8px", "paddingBottom": "6px"}, "config": {"name": "AI Recommendation", "type": "label"}, "classes": []}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Recommendation", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Recommendation", "keyName": "recommendation"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Recommended Amount", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Amount", "keyName": "recommended_amount"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Match Summary", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Match Summary", "keyName": "match_summary"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "AI Reasoning", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Reasoning", "keyName": "ai_reasoning"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "AI Confidence", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Confidence", "keyName": "ai_confidence"}}}, {"type": "element", "style": {"display": "inline-block", "marginTop": "20px", "marginRight": "8px"}, "config": {"icon": "check_circle", "name": "Approve Payment", "type": "button", "params": {"activity_id": "p2p-act-approve-payment", "workflow_id": "wf_p2p_invoice_demo"}, "action_end": [{"type": "refresh_page"}], "job_template": "perform_activity"}, "classes": ["z-btn-primary"]}, {"type": "element", "style": {"display": "inline-block", "marginTop": "20px", "marginRight": "8px"}, "config": {"icon": "cancel", "name": "Reject Payment", "type": "button", "params": {"activity_id": "p2p-act-reject-payment", "workflow_id": "wf_p2p_invoice_demo"}, "action_end": [{"type": "refresh_page"}], "job_template": "perform_activity"}, "classes": ["z-btn-outline"]}, {"type": "element", "style": {"display": "inline-block", "marginTop": "20px"}, "config": {"icon": "pause_circle", "name": "Hold Payment", "type": "button", "params": {"activity_id": "p2p-act-hold-payment", "workflow_id": "wf_p2p_invoice_demo"}, "action_end": [{"type": "refresh_page"}], "job_template": "perform_activity"}, "classes": ["z-btn-outline"]}]'::jsonb, 29513) ON CONFLICT (id) DO NOTHING; + +-- Form Screens +INSERT INTO tbl_appconfig_form_screens (id, source_form_id, activity_uid, device_type, layout, grid_config, app_id) VALUES (20136, 20094, 'p2p-act-submit-invoice', 'desktop', '[]'::jsonb, '[{"h": 1, "i": "p2p-field-9401", "w": 6, "x": 0, "y": 0}, {"h": 1, "i": "p2p-field-9402", "w": 6, "x": 6, "y": 0}, {"h": 1, "i": "p2p-field-9403", "w": 6, "x": 0, "y": 1}, {"h": 1, "i": "p2p-field-9404", "w": 6, "x": 6, "y": 1}, {"h": 1, "i": "p2p-field-9405", "w": 6, "x": 0, "y": 2}, {"h": 1, "i": "p2p-field-9406", "w": 6, "x": 6, "y": 2}, {"h": 1, "i": "p2p-field-9407", "w": 6, "x": 0, "y": 3}, {"h": 1, "i": "p2p-field-9408", "w": 6, "x": 6, "y": 3}, {"h": 1, "i": "p2p-field-9409", "w": 6, "x": 0, "y": 4}, {"h": 1, "i": "p2p-field-9410", "w": 6, "x": 6, "y": 4}]'::jsonb, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_form_screens (id, source_form_id, activity_uid, device_type, layout, grid_config, app_id) VALUES (20137, 20095, 'p2p-act-provide-clarification', 'desktop', '[]'::jsonb, '[{"h": 1, "i": "p2p-field-9415", "w": 12, "x": 0, "y": 0}, {"h": 1, "i": "p2p-field-9416", "w": 12, "x": 0, "y": 1}, {"h": 1, "i": "p2p-field-9417", "w": 12, "x": 0, "y": 2}]'::jsonb, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_form_screens (id, source_form_id, activity_uid, device_type, layout, grid_config, app_id) VALUES (20138, 20096, 'p2p-act-approve-payment', 'desktop', '[]'::jsonb, '[{"h": 1, "i": "p2p-field-9423", "w": 6, "x": 0, "y": 0}, {"h": 1, "i": "p2p-field-9424", "w": 6, "x": 6, "y": 0}]'::jsonb, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_form_screens (id, source_form_id, activity_uid, device_type, layout, grid_config, app_id) VALUES (20139, 20097, 'p2p-act-reject-payment', 'desktop', '[]'::jsonb, '[{"h": 1, "i": "p2p-field-9425", "w": 12, "x": 0, "y": 0}, {"h": 1, "i": "p2p-field-9426", "w": 12, "x": 0, "y": 1}]'::jsonb, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_form_screens (id, source_form_id, activity_uid, device_type, layout, grid_config, app_id) VALUES (20140, 20098, 'p2p-act-hold-payment', 'desktop', '[]'::jsonb, '[{"h": 1, "i": "p2p-field-9427", "w": 12, "x": 0, "y": 0}, {"h": 1, "i": "p2p-field-9428", "w": 12, "x": 0, "y": 1}]'::jsonb, 20) ON CONFLICT (id) DO NOTHING; + +-- Header Config +INSERT INTO tbl_appconfig_header_config (id, app_id, device_type, config) VALUES (20001, 20, 'desktop', '{"slots": {"left": ["logo", "nav"], "right": ["profile"], "center": []}, "layout": {"type": "classic", "height": "56px", "position": "sticky", "full_width": true}, "components": {"nav": {"items": [{"id": "nav_vendor", "icon": "receipt_long", "type": "screen", "label": "My Invoices", "screen_id": 29631}, {"id": "nav_clarifications", "icon": "help_outline", "type": "screen", "label": "Pending Clarifications", "screen_id": 29632}, {"id": "nav_finance", "icon": "account_balance", "type": "screen", "label": "Finance Review", "screen_id": 29633}, {"id": "nav_all", "icon": "list_alt", "type": "screen", "label": "All Invoices", "screen_id": 29634}]}, "logo": {"text": "P2P Invoice System", "display_type": "text"}, "profile": {"shape": "circle", "show_name": true}}}'::jsonb) ON CONFLICT (id) DO NOTHING; + +-- 3. Workflow design +INSERT INTO workflow.tbl_workflows (id, uid, app_id, name, description) VALUES (29100, 'wf_p2p_invoice_demo', 20, 'P2P Invoice Validation', 'AI-powered invoice validation with department clarification and finance approval') ON CONFLICT (id) DO NOTHING; + +-- Workflow versions + + +-- States +INSERT INTO workflow.tbl_wf_states (id, uid, version_id, name, description, type) VALUES (29203, 'p2p-state-awaiting-clarification', 29100, 'Awaiting Clarification', '', 'STANDARD') ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_states (id, uid, version_id, name, description, type) VALUES (20057, 'p2p-state-invoice-submitted', 29100, 'Invoice Submitted', '', 'STANDARD') ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_states (id, uid, version_id, name, description, type) VALUES (20058, 'p2p-state-ai-analysis', 29100, 'AI Analysis', '', 'STANDARD') ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_states (id, uid, version_id, name, description, type) VALUES (20059, 'p2p-state-finance-review', 29100, 'Finance Review', '', 'STANDARD') ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_states (id, uid, version_id, name, description, type) VALUES (20060, 'p2p-state-approved', 29100, 'Approved', '', 'END') ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_states (id, uid, version_id, name, description, type) VALUES (20061, 'p2p-state-rejected', 29100, 'Rejected', '', 'END') ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_states (id, uid, version_id, name, description, type) VALUES (20062, 'p2p-state-on-hold', 29100, 'On Hold', '', 'END') ON CONFLICT (id) DO NOTHING; + +-- Activities +INSERT INTO workflow.tbl_wf_activities (id, activity_uid, workflow_version_id, name, type) VALUES (20070, 'p2p-act-submit-invoice', 29100, 'Submit Invoice', 'INIT') ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_activities (id, activity_uid, workflow_version_id, name, type) VALUES (20071, 'p2p-act-request-clarification', 29100, 'Request Clarification', 'NORMAL') ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_activities (id, activity_uid, workflow_version_id, name, type) VALUES (20072, 'p2p-act-submit-recommendation', 29100, 'Submit Recommendation', 'NORMAL') ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_activities (id, activity_uid, workflow_version_id, name, type) VALUES (20073, 'p2p-act-provide-clarification', 29100, 'Provide Clarification', 'NORMAL') ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_activities (id, activity_uid, workflow_version_id, name, type) VALUES (20074, 'p2p-act-approve-payment', 29100, 'Approve Payment', 'NORMAL') ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_activities (id, activity_uid, workflow_version_id, name, type) VALUES (20075, 'p2p-act-reject-payment', 29100, 'Reject Payment', 'NORMAL') ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_activities (id, activity_uid, workflow_version_id, name, type) VALUES (20076, 'p2p-act-hold-payment', 29100, 'Hold Payment', 'NORMAL') ON CONFLICT (id) DO NOTHING; + +-- Activity fields +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9401', 'vendor_id', 20070, 'Vendor ID', 'local', 'text', true) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9402', 'vendor_name', 20070, 'Vendor Name', 'local', 'text', true) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9403', 'invoice_number', 20070, 'Invoice Number', 'local', 'text', true) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9404', 'invoice_date', 20070, 'Invoice Date', 'local', 'date', true) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9405', 'po_number', 20070, 'PO Number', 'local', 'text', true) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9406', 'currency', 20070, 'Currency', 'local', 'text', false) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9407', 'total_amount', 20070, 'Total Amount', 'local', 'number', true) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9408', 'tax_amount', 20070, 'Tax Amount', 'local', 'number', false) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9409', 'payment_terms', 20070, 'Payment Terms', 'local', 'text', false) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9410', 'notes', 20070, 'Notes', 'local', 'text', false) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9411', 'target_department', 20071, 'Target Department', 'local', 'text', true) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9412', 'clarification_question', 20071, 'Question', 'local', 'text', true) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9413', 'clarification_context', 20071, 'Context', 'local', 'text', false) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9414', 'analysis_so_far', 20071, 'Analysis So Far', 'local', 'text', false) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9415', 'response_text', 20073, 'Response', 'local', 'text', true) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9416', 'confirmed_quantity', 20073, 'Confirmed Quantity', 'local', 'number', false) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9417', 'response_notes', 20073, 'Additional Notes', 'local', 'text', false) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9418', 'recommendation', 20072, 'Recommendation', 'local', 'text', true) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9419', 'recommended_amount', 20072, 'Recommended Payment Amount', 'local', 'number', false) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9420', 'match_summary', 20072, 'Match Summary', 'local', 'text', false) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9421', 'ai_reasoning', 20072, 'AI Reasoning', 'local', 'text', false) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9422', 'ai_confidence', 20072, 'AI Confidence', 'local', 'number', false) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9423', 'approved_amount', 20074, 'Approved Amount', 'local', 'number', true) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9424', 'reviewer_notes', 20074, 'Reviewer Notes', 'local', 'text', false) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9425', 'rejection_reason', 20075, 'Rejection Reason', 'local', 'text', true) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9426', 'reviewer_notes', 20075, 'Reviewer Notes', 'local', 'text', false) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9427', 'hold_reason', 20076, 'Hold Reason', 'local', 'text', true) ON CONFLICT DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_fields (uid, field_s_id, activity_id, name, field_type, data_type, is_mandatory) VALUES ('p2p-field-9428', 'reviewer_notes', 20076, 'Reviewer Notes', 'local', 'text', false) ON CONFLICT DO NOTHING; + +-- Activity triggers +INSERT INTO workflow.tbl_wf_activity_triggers (id, activity_id, trigger_uid, trigger_config) VALUES (67, 20070, 'trigger_p2p_submit', '{}'::jsonb) ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_triggers (id, activity_id, trigger_uid, trigger_config) VALUES (68, 20073, 'trigger_p2p_clarify', '{}'::jsonb) ON CONFLICT (id) DO NOTHING; + +-- Activity trigger nodes +INSERT INTO workflow.tbl_wf_activity_trigger_nodes (id, trigger_id, name, type, config, edges, ui_config) VALUES ('a0a0a0a0-0000-4000-8000-000000093011', 67, 'Start', 'start', '{}'::jsonb, '[{"target": "a0a0a0a0-0000-4000-8000-000000093012", "source_handle": "output"}]'::jsonb, NULL) ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_trigger_nodes (id, trigger_id, name, type, config, edges, ui_config) VALUES ('a0a0a0a0-0000-4000-8000-000000093012', 67, 'AI Employee', 'aiEmployee', '{"ai_user_id": "29100"}'::jsonb, '[{"target": "a0a0a0a0-0000-4000-8000-000000093013", "source_handle": "output"}]'::jsonb, NULL) ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_trigger_nodes (id, trigger_id, name, type, config, edges, ui_config) VALUES ('a0a0a0a0-0000-4000-8000-000000093013', 67, 'Complete', 'response', '{"message": "AI Employee task dispatched", "success": true, "status_code": 200}'::jsonb, '[]'::jsonb, NULL) ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_trigger_nodes (id, trigger_id, name, type, config, edges, ui_config) VALUES ('a0a0a0a0-0000-4000-8000-000000093041', 68, 'Start', 'start', '{}'::jsonb, '[{"target": "a0a0a0a0-0000-4000-8000-000000093042", "source_handle": "output"}]'::jsonb, NULL) ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_trigger_nodes (id, trigger_id, name, type, config, edges, ui_config) VALUES ('a0a0a0a0-0000-4000-8000-000000093042', 68, 'AI Employee', 'aiEmployee', '{"ai_user_id": "29100"}'::jsonb, '[{"target": "a0a0a0a0-0000-4000-8000-000000093043", "source_handle": "output"}]'::jsonb, NULL) ON CONFLICT (id) DO NOTHING; +INSERT INTO workflow.tbl_wf_activity_trigger_nodes (id, trigger_id, name, type, config, edges, ui_config) VALUES ('a0a0a0a0-0000-4000-8000-000000093043', 68, 'Complete', 'response', '{"message": "AI Employee task dispatched", "success": true, "status_code": 200}'::jsonb, '[]'::jsonb, NULL) ON CONFLICT (id) DO NOTHING; + +-- Activity permissions + +-- 4. AI Employee +INSERT INTO aiemployee.tbl_ai_employees (id, user_id, org_id, name, model, autonomy_level, config, status) VALUES (20, '29100', '20', 'Priya AI Finance (P2P Demo)', 'claude-sonnet-4-5-20250929', 'semi_autonomous', '{"mcp_servers": [], "rate_limits": {"max_tasks_per_day": 500, "max_tasks_per_hour": 100, "confidence_threshold": 0.5, "max_tasks_per_minute": 10, "max_llm_calls_per_task": 12}, "available_tools": {"agentic_tools": ["29110", "29111", "29112", "29113"], "autonomous_agents": []}, "monthly_budget_usd": 200, "max_concurrent_tasks": 3}'::jsonb, 'active') ON CONFLICT (id) DO NOTHING; + +-- AI Employee appconfig +INSERT INTO aiemployee.tbl_appconfig_ai_employees (id, user_id, org_id, name, model, autonomy_level, config, status, email, password) VALUES (20038, '29100', '20', 'Priya AI Finance (P2P Demo)', 'claude-sonnet-4-5-20250929', 'semi_autonomous', '{"mcp_servers": [], "rate_limits": {"max_tasks_per_day": 500, "max_tasks_per_hour": 100, "confidence_threshold": 0.5, "max_tasks_per_minute": 10, "max_llm_calls_per_task": 12}, "available_tools": {"agentic_tools": ["29110", "29111", "29112", "29113"], "autonomous_agents": []}, "monthly_budget_usd": 200, "max_concurrent_tasks": 3}'::jsonb, 'active', '', '') ON CONFLICT (id) DO NOTHING; + +-- AI Employee registry +INSERT INTO aiemployee.tbl_ai_employee_registry (ai_user_id, service_url, status) VALUES ('29100', 'http://localhost:8090', 'running') ON CONFLICT (ai_user_id) DO NOTHING; + +-- 5. Agentic tools + +-- 6. DB Connection +INSERT INTO tbl_org_db_connections (id, org_id, name, type, host, port, "user", password, database_name, ssl_mode) VALUES (5, 20, 'P2P Azure DB', 'postgres', 'studio-v2-pg.postgres.database.azure.com', 5432, 'studiov2pgadmin', 'YmzkpmVprw0Fsn8s0cvR', 'sm', 'require') ON CONFLICT (id) DO NOTHING; + +-- ============================================================ +-- 7. P2P DEMO DATA (p2p_demo schema) +-- ============================================================ +CREATE SCHEMA IF NOT EXISTS p2p_demo; + +CREATE TABLE p2p_demo.contract_line_items ( + id integer NOT NULL, + contract_id text, + product_code text NOT NULL, + description text, + unit_price numeric(12,2) NOT NULL, + currency text DEFAULT 'INR'::text +); + + +ALTER TABLE p2p_demo.contract_line_items OWNER TO postgres; + +-- +-- Name: contract_line_items_id_seq; Type: SEQUENCE; Schema: p2p_demo; Owner: postgres +-- + +CREATE SEQUENCE p2p_demo.contract_line_items_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE p2p_demo.contract_line_items_id_seq OWNER TO postgres; + +-- +-- Name: contract_line_items_id_seq; Type: SEQUENCE OWNED BY; Schema: p2p_demo; Owner: postgres +-- + +ALTER SEQUENCE p2p_demo.contract_line_items_id_seq OWNED BY p2p_demo.contract_line_items.id; + + +-- +-- Name: contracts; Type: TABLE; Schema: p2p_demo; Owner: postgres +-- + +CREATE TABLE p2p_demo.contracts ( + contract_id text NOT NULL, + vendor_id text NOT NULL, + vendor_name text NOT NULL, + effective_date date, + expiry_date date, + status text DEFAULT 'active'::text, + payment_terms text, + price_tolerance_pct numeric(5,2) DEFAULT 2.0, + quantity_tolerance_pct numeric(5,2) DEFAULT 5.0, + created_at timestamp without time zone DEFAULT now() +); + + +ALTER TABLE p2p_demo.contracts OWNER TO postgres; + +-- +-- Name: goods_receipts; Type: TABLE; Schema: p2p_demo; Owner: postgres +-- + +CREATE TABLE p2p_demo.goods_receipts ( + gr_number text NOT NULL, + po_number text NOT NULL, + vendor_id text NOT NULL, + receipt_date date, + received_by text, + notes text, + created_at timestamp without time zone DEFAULT now() +); + + +ALTER TABLE p2p_demo.goods_receipts OWNER TO postgres; + +-- +-- Name: gr_line_items; Type: TABLE; Schema: p2p_demo; Owner: postgres +-- + +CREATE TABLE p2p_demo.gr_line_items ( + id integer NOT NULL, + gr_number text, + product_code text NOT NULL, + quantity_received integer NOT NULL, + condition text DEFAULT 'good'::text +); + + +ALTER TABLE p2p_demo.gr_line_items OWNER TO postgres; + +-- +-- Name: gr_line_items_id_seq; Type: SEQUENCE; Schema: p2p_demo; Owner: postgres +-- + +CREATE SEQUENCE p2p_demo.gr_line_items_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE p2p_demo.gr_line_items_id_seq OWNER TO postgres; + +-- +-- Name: gr_line_items_id_seq; Type: SEQUENCE OWNED BY; Schema: p2p_demo; Owner: postgres +-- + +ALTER SEQUENCE p2p_demo.gr_line_items_id_seq OWNED BY p2p_demo.gr_line_items.id; + + +-- +-- Name: payments; Type: TABLE; Schema: p2p_demo; Owner: postgres +-- + +CREATE TABLE p2p_demo.payments ( + payment_id text NOT NULL, + invoice_number text, + po_number text, + vendor_id text NOT NULL, + amount numeric(14,2) NOT NULL, + payment_date date, + status text DEFAULT 'completed'::text, + created_at timestamp without time zone DEFAULT now() +); + + +ALTER TABLE p2p_demo.payments OWNER TO postgres; + +-- +-- Name: po_line_items; Type: TABLE; Schema: p2p_demo; Owner: postgres +-- + +CREATE TABLE p2p_demo.po_line_items ( + id integer NOT NULL, + po_number text, + product_code text NOT NULL, + description text, + quantity integer NOT NULL, + unit_price numeric(12,2) NOT NULL +); + + +ALTER TABLE p2p_demo.po_line_items OWNER TO postgres; + +-- +-- Name: po_line_items_id_seq; Type: SEQUENCE; Schema: p2p_demo; Owner: postgres +-- + +CREATE SEQUENCE p2p_demo.po_line_items_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE p2p_demo.po_line_items_id_seq OWNER TO postgres; + +-- +-- Name: po_line_items_id_seq; Type: SEQUENCE OWNED BY; Schema: p2p_demo; Owner: postgres +-- + +ALTER SEQUENCE p2p_demo.po_line_items_id_seq OWNED BY p2p_demo.po_line_items.id; + + +-- +-- Name: purchase_orders; Type: TABLE; Schema: p2p_demo; Owner: postgres +-- + +CREATE TABLE p2p_demo.purchase_orders ( + po_number text NOT NULL, + vendor_id text NOT NULL, + vendor_name text NOT NULL, + contract_id text, + order_date date, + expected_delivery date, + status text DEFAULT 'open'::text, + total_amount numeric(14,2), + created_at timestamp without time zone DEFAULT now() +); + + +ALTER TABLE p2p_demo.purchase_orders OWNER TO postgres; + +-- +-- Name: tbl_messages; Type: TABLE; Schema: pipeline_ai; Owner: postgres +-- + +CREATE TABLE pipeline_ai.tbl_messages ( + id bigint NOT NULL, + session_id bigint, + role text, + content text, + metadata jsonb DEFAULT '{}'::jsonb, + created_at timestamp with time zone +); + + +ALTER TABLE pipeline_ai.tbl_messages OWNER TO postgres; + +-- + +COMMIT; + +-- User agent assignments + +-- Activity permissions + +-- Agentic tools +INSERT INTO agents.tbl_agentic_tools (id, org_id, group_id, name, description, flow_config, status, icon) VALUES (29112, 20, 20, 'fetch_contract', 'Fetch contract details by contract_id or vendor_id. Returns contract terms, pricing, tolerances. Use parameter: contract_id (preferred) or vendor_id.', E'{"edges": [{"id": "e1", "type": "custom", "source": "trigger-1", "target": "db-query-1", "sourceHandle": "output", "targetHandle": "input"}, {"id": "e2", "type": "custom", "source": "db-query-1", "target": "success-1", "sourceHandle": "output", "targetHandle": "input"}], "nodes": [{"id": "trigger-1", "data": {"label": "Input", "config": {"path": "/", "method": "POST"}}, "type": "webhookTrigger", "position": {"x": 100, "y": 50}}, {"id": "db-query-1", "data": {"label": "Query p2p_demo", "config": {"query": "SELECT json_build_object(\\\\n\\\\t\\\\t\\\\t\\\\t''contract_id'', c.contract_id,\\\\n\\\\t\\\\t\\\\t\\\\t''vendor_id'', c.vendor_id,\\\\n\\\\t\\\\t\\\\t\\\\t''vendor_name'', c.vendor_name,\\\\n\\\\t\\\\t\\\\t\\\\t''effective_date'', c.effective_date,\\\\n\\\\t\\\\t\\\\t\\\\t''expiry_date'', c.expiry_date,\\\\n\\\\t\\\\t\\\\t\\\\t''status'', c.status,\\\\n\\\\t\\\\t\\\\t\\\\t''payment_terms'', c.payment_terms,\\\\n\\\\t\\\\t\\\\t\\\\t''price_tolerance_pct'', c.price_tolerance_pct,\\\\n\\\\t\\\\t\\\\t\\\\t''quantity_tolerance_pct'', c.quantity_tolerance_pct,\\\\n\\\\t\\\\t\\\\t\\\\t''line_items'', COALESCE((\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tSELECT json_agg(json_build_object(\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''product_code'', cli.product_code,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''description'', cli.description,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''unit_price'', cli.unit_price,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''currency'', cli.currency\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t))\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tFROM p2p_demo.contract_line_items cli WHERE cli.contract_id = c.contract_id\\\\n\\\\t\\\\t\\\\t\\\\t), ''[]''::json)\\\\n\\\\t\\\\t\\\\t) AS result\\\\n\\\\t\\\\t\\\\tFROM p2p_demo.contracts c\\\\n\\\\t\\\\t\\\\tWHERE c.contract_id = ''{{contract_id}}''\\\\n\\\\t\\\\t\\\\t OR c.vendor_id = ''{{vendor_id}}''\\\\n\\\\t\\\\t\\\\tLIMIT 1", "db_type": "postgresql", "operation": "raw", "connection": "{{env.DATABASE_URL}}", "result_limit": 50, "output_variable": "result"}}, "type": "databaseQuery", "position": {"x": 100, "y": 200}}, {"id": "success-1", "data": {"label": "Output", "config": {"output_field": "result"}}, "type": "success", "position": {"x": 100, "y": 350}}]}'::jsonb, 'active', '') ON CONFLICT (id) DO NOTHING; +INSERT INTO agents.tbl_agentic_tools (id, org_id, group_id, name, description, flow_config, status, icon) VALUES (29110, 20, 20, 'fetch_purchase_order', 'Fetch purchase order details by PO number. Returns PO header (vendor, status, total, dates) and line items (product, quantity, unit price). Use parameter: po_number.', E'{"edges": [{"id": "e1", "type": "custom", "source": "trigger-1", "target": "db-query-1", "sourceHandle": "output", "targetHandle": "input"}, {"id": "e2", "type": "custom", "source": "db-query-1", "target": "success-1", "sourceHandle": "output", "targetHandle": "input"}], "nodes": [{"id": "trigger-1", "data": {"label": "Input", "config": {"path": "/", "method": "POST"}}, "type": "webhookTrigger", "position": {"x": 100, "y": 50}}, {"id": "db-query-1", "data": {"label": "Query p2p_demo", "config": {"query": "SELECT json_build_object(\\\\n\\\\t\\\\t\\\\t\\\\t''po_number'', po.po_number,\\\\n\\\\t\\\\t\\\\t\\\\t''vendor_id'', po.vendor_id,\\\\n\\\\t\\\\t\\\\t\\\\t''vendor_name'', po.vendor_name,\\\\n\\\\t\\\\t\\\\t\\\\t''contract_id'', po.contract_id,\\\\n\\\\t\\\\t\\\\t\\\\t''order_date'', po.order_date,\\\\n\\\\t\\\\t\\\\t\\\\t''expected_delivery'', po.expected_delivery,\\\\n\\\\t\\\\t\\\\t\\\\t''status'', po.status,\\\\n\\\\t\\\\t\\\\t\\\\t''total_amount'', po.total_amount,\\\\n\\\\t\\\\t\\\\t\\\\t''line_items'', COALESCE((\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tSELECT json_agg(json_build_object(\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''product_code'', li.product_code,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''description'', li.description,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''quantity'', li.quantity,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''unit_price'', li.unit_price\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t))\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tFROM p2p_demo.po_line_items li WHERE li.po_number = po.po_number\\\\n\\\\t\\\\t\\\\t\\\\t), ''[]''::json)\\\\n\\\\t\\\\t\\\\t) AS result\\\\n\\\\t\\\\t\\\\tFROM p2p_demo.purchase_orders po\\\\n\\\\t\\\\t\\\\tWHERE po.po_number = ''{{po_number}}''", "db_type": "postgresql", "operation": "raw", "connection": "{{env.DATABASE_URL}}", "result_limit": 50, "output_variable": "result"}}, "type": "databaseQuery", "position": {"x": 100, "y": 200}}, {"id": "success-1", "data": {"label": "Output", "config": {"output_field": "result"}}, "type": "success", "position": {"x": 100, "y": 350}}]}'::jsonb, 'active', '') ON CONFLICT (id) DO NOTHING; +INSERT INTO agents.tbl_agentic_tools (id, org_id, group_id, name, description, flow_config, status, icon) VALUES (29111, 20, 20, 'fetch_goods_receipt', 'Fetch goods receipt records for a PO number. Returns all delivery records with received quantities, dates, and notes. Use parameter: po_number.', E'{"edges": [{"id": "e1", "type": "custom", "source": "trigger-1", "target": "db-query-1", "sourceHandle": "output", "targetHandle": "input"}, {"id": "e2", "type": "custom", "source": "db-query-1", "target": "success-1", "sourceHandle": "output", "targetHandle": "input"}], "nodes": [{"id": "trigger-1", "data": {"label": "Input", "config": {"path": "/", "method": "POST"}}, "type": "webhookTrigger", "position": {"x": 100, "y": 50}}, {"id": "db-query-1", "data": {"label": "Query p2p_demo", "config": {"query": "SELECT json_build_object(\\\\n\\\\t\\\\t\\\\t\\\\t''po_number'', ''{{po_number}}'',\\\\n\\\\t\\\\t\\\\t\\\\t''receipts'', COALESCE((\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tSELECT json_agg(json_build_object(\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''gr_number'', gr.gr_number,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''receipt_date'', gr.receipt_date,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''received_by'', gr.received_by,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''notes'', gr.notes,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''line_items'', COALESCE((\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tSELECT json_agg(json_build_object(\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''product_code'', gli.product_code,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''quantity_received'', gli.quantity_received,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''condition'', gli.condition\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t))\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t\\\\tFROM p2p_demo.gr_line_items gli WHERE gli.gr_number = gr.gr_number\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t), ''[]''::json)\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t))\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tFROM p2p_demo.goods_receipts gr WHERE gr.po_number = ''{{po_number}}''\\\\n\\\\t\\\\t\\\\t\\\\t), ''[]''::json),\\\\n\\\\t\\\\t\\\\t\\\\t''total_received'', COALESCE((\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tSELECT SUM(gli.quantity_received)\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tFROM p2p_demo.goods_receipts gr\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tJOIN p2p_demo.gr_line_items gli ON gli.gr_number = gr.gr_number\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tWHERE gr.po_number = ''{{po_number}}''\\\\n\\\\t\\\\t\\\\t\\\\t), 0)\\\\n\\\\t\\\\t\\\\t) AS result", "db_type": "postgresql", "operation": "raw", "connection": "{{env.DATABASE_URL}}", "result_limit": 50, "output_variable": "result"}}, "type": "databaseQuery", "position": {"x": 100, "y": 200}}, {"id": "success-1", "data": {"label": "Output", "config": {"output_field": "result"}}, "type": "success", "position": {"x": 100, "y": 350}}]}'::jsonb, 'active', '') ON CONFLICT (id) DO NOTHING; +INSERT INTO agents.tbl_agentic_tools (id, org_id, group_id, name, description, flow_config, status, icon) VALUES (29113, 20, 20, 'fetch_payment_history', 'Fetch payment history for a PO number or vendor. Returns all payments made, total paid amount. Use parameter: po_number (preferred) or vendor_id.', E'{"edges": [{"id": "e1", "type": "custom", "source": "trigger-1", "target": "db-query-1", "sourceHandle": "output", "targetHandle": "input"}, {"id": "e2", "type": "custom", "source": "db-query-1", "target": "success-1", "sourceHandle": "output", "targetHandle": "input"}], "nodes": [{"id": "trigger-1", "data": {"label": "Input", "config": {"path": "/", "method": "POST"}}, "type": "webhookTrigger", "position": {"x": 100, "y": 50}}, {"id": "db-query-1", "data": {"label": "Query p2p_demo", "config": {"query": "SELECT json_build_object(\\\\n\\\\t\\\\t\\\\t\\\\t''payments'', COALESCE((\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tSELECT json_agg(json_build_object(\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''payment_id'', p.payment_id,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''invoice_number'', p.invoice_number,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''po_number'', p.po_number,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''amount'', p.amount,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''payment_date'', p.payment_date,\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t\\\\t''status'', p.status\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t))\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tFROM p2p_demo.payments p\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tWHERE p.po_number = ''{{po_number}}'' OR p.vendor_id = ''{{vendor_id}}''\\\\n\\\\t\\\\t\\\\t\\\\t), ''[]''::json),\\\\n\\\\t\\\\t\\\\t\\\\t''total_paid'', COALESCE((\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tSELECT SUM(p.amount)\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tFROM p2p_demo.payments p\\\\n\\\\t\\\\t\\\\t\\\\t\\\\tWHERE (p.po_number = ''{{po_number}}'' OR p.vendor_id = ''{{vendor_id}}'')\\\\n\\\\t\\\\t\\\\t\\\\t\\\\t AND p.status = ''completed''\\\\n\\\\t\\\\t\\\\t\\\\t), 0)\\\\n\\\\t\\\\t\\\\t) AS result", "db_type": "postgresql", "operation": "raw", "connection": "{{env.DATABASE_URL}}", "result_limit": 50, "output_variable": "result"}}, "type": "databaseQuery", "position": {"x": 100, "y": 200}}, {"id": "success-1", "data": {"label": "Output", "config": {"output_field": "result"}}, "type": "success", "position": {"x": 100, "y": 350}}]}'::jsonb, 'active', '') ON CONFLICT (id) DO NOTHING; + +-- ============================================================ +-- 7. P2P DEMO DATA (p2p_demo schema) +-- ============================================================ +-- Import from: /Users/bhanuprakash/Downloads/sm_db.sql +-- Extract p2p_demo tables/data separately using: +-- grep -A lines for p2p_demo CREATE TABLE and COPY statements + +COMMIT; diff --git a/p2p_demo_schema.sql b/p2p_demo_schema.sql new file mode 100644 index 0000000..7bd985f --- /dev/null +++ b/p2p_demo_schema.sql @@ -0,0 +1,164 @@ +-- P2P Demo Schema Data +CREATE SCHEMA IF NOT EXISTS p2p_demo; + +CREATE TABLE p2p_demo.contract_line_items ( + id integer NOT NULL, + contract_id text, + product_code text NOT NULL, + description text, + unit_price numeric(12,2) NOT NULL, + currency text DEFAULT 'INR'::text +); + +ALTER TABLE p2p_demo.contract_line_items OWNER TO postgres; +CREATE SEQUENCE p2p_demo.contract_line_items_id_seq +ALTER SEQUENCE p2p_demo.contract_line_items_id_seq OWNER TO postgres; +ALTER SEQUENCE p2p_demo.contract_line_items_id_seq OWNED BY p2p_demo.contract_line_items.id; +CREATE TABLE p2p_demo.contracts ( + contract_id text NOT NULL, + vendor_id text NOT NULL, + vendor_name text NOT NULL, + effective_date date, + expiry_date date, + status text DEFAULT 'active'::text, + payment_terms text, + price_tolerance_pct numeric(5,2) DEFAULT 2.0, + quantity_tolerance_pct numeric(5,2) DEFAULT 5.0, + created_at timestamp without time zone DEFAULT now() +); + +ALTER TABLE p2p_demo.contracts OWNER TO postgres; +CREATE TABLE p2p_demo.goods_receipts ( + gr_number text NOT NULL, + po_number text NOT NULL, + vendor_id text NOT NULL, + receipt_date date, + received_by text, + notes text, + created_at timestamp without time zone DEFAULT now() +); + +ALTER TABLE p2p_demo.goods_receipts OWNER TO postgres; +CREATE TABLE p2p_demo.gr_line_items ( + id integer NOT NULL, + gr_number text, + product_code text NOT NULL, + quantity_received integer NOT NULL, + condition text DEFAULT 'good'::text +); + +ALTER TABLE p2p_demo.gr_line_items OWNER TO postgres; +CREATE SEQUENCE p2p_demo.gr_line_items_id_seq +ALTER SEQUENCE p2p_demo.gr_line_items_id_seq OWNER TO postgres; +ALTER SEQUENCE p2p_demo.gr_line_items_id_seq OWNED BY p2p_demo.gr_line_items.id; +CREATE TABLE p2p_demo.payments ( + payment_id text NOT NULL, + invoice_number text, + po_number text, + vendor_id text NOT NULL, + amount numeric(14,2) NOT NULL, + payment_date date, + status text DEFAULT 'completed'::text, + created_at timestamp without time zone DEFAULT now() +); + +ALTER TABLE p2p_demo.payments OWNER TO postgres; +CREATE TABLE p2p_demo.po_line_items ( + id integer NOT NULL, + po_number text, + product_code text NOT NULL, + description text, + quantity integer NOT NULL, + unit_price numeric(12,2) NOT NULL +); + +ALTER TABLE p2p_demo.po_line_items OWNER TO postgres; +CREATE SEQUENCE p2p_demo.po_line_items_id_seq +ALTER SEQUENCE p2p_demo.po_line_items_id_seq OWNER TO postgres; +ALTER SEQUENCE p2p_demo.po_line_items_id_seq OWNED BY p2p_demo.po_line_items.id; +CREATE TABLE p2p_demo.purchase_orders ( + po_number text NOT NULL, + vendor_id text NOT NULL, + vendor_name text NOT NULL, + contract_id text, + order_date date, + expected_delivery date, + status text DEFAULT 'open'::text, + total_amount numeric(14,2), + created_at timestamp without time zone DEFAULT now() +); + +ALTER TABLE p2p_demo.purchase_orders OWNER TO postgres; +ALTER TABLE ONLY p2p_demo.contract_line_items ALTER COLUMN id SET DEFAULT nextval('p2p_demo.contract_line_items_id_seq'::regclass); +ALTER TABLE ONLY p2p_demo.contract_line_items ALTER COLUMN id SET DEFAULT nextval('p2p_demo.contract_line_items_id_seq'::regclass); +ALTER TABLE ONLY p2p_demo.gr_line_items ALTER COLUMN id SET DEFAULT nextval('p2p_demo.gr_line_items_id_seq'::regclass); +ALTER TABLE ONLY p2p_demo.gr_line_items ALTER COLUMN id SET DEFAULT nextval('p2p_demo.gr_line_items_id_seq'::regclass); +ALTER TABLE ONLY p2p_demo.po_line_items ALTER COLUMN id SET DEFAULT nextval('p2p_demo.po_line_items_id_seq'::regclass); +ALTER TABLE ONLY p2p_demo.po_line_items ALTER COLUMN id SET DEFAULT nextval('p2p_demo.po_line_items_id_seq'::regclass); +COPY p2p_demo.contract_line_items (id, contract_id, product_code, description, unit_price, currency) FROM stdin; +233 CNT-100 PRD-101 Steel Rods 12mm 1000.00 INR +234 CNT-100 PRD-102 Steel Plates 5mm 2500.00 INR +235 CNT-200 PRD-201 A4 Paper Ream (500 sheets) 200.00 INR +236 CNT-200 PRD-202 Printer Ink Cartridge 1500.00 INR +237 CNT-300 PRD-301 Circuit Board Type-A 500.00 INR +238 CNT-300 PRD-302 LED Panel 24inch 3500.00 INR +239 CNT-400 PRD-401 Safety Helmet 150.00 INR +240 CNT-400 PRD-402 Industrial Gloves (pair) 80.00 INR +\. + +COPY p2p_demo.contracts (contract_id, vendor_id, vendor_name, effective_date, expiry_date, status, payment_terms, price_tolerance_pct, quantity_tolerance_pct, created_at) FROM stdin; +CNT-100 VND-001 Tata Steel Ltd 2026-01-01 2026-12-31 active Net 30 2.00 5.00 2026-03-30 18:34:11.089882 +CNT-200 VND-002 Reliance Office Supplies 2026-01-01 2026-12-31 active Net 15 3.00 5.00 2026-03-30 18:34:11.091337 +CNT-300 VND-003 Bharat Electronics 2026-01-01 2026-12-31 active Net 30 2.00 5.00 2026-03-30 18:34:11.092484 +CNT-400 VND-004 Godrej Industrial 2026-01-01 2026-12-31 active 2/10 Net 30 2.00 5.00 2026-03-30 18:34:11.093581 +\. + +COPY p2p_demo.goods_receipts (gr_number, po_number, vendor_id, receipt_date, received_by, notes, created_at) FROM stdin; +GR-2001 PO-2001 VND-002 2026-03-18 Amit Kumar Full delivery received. All items in good condition. 2026-03-30 18:34:11.100119 +GR-1001 PO-1001 VND-001 2026-03-18 Rajesh Sharma Partial delivery. 700 of 1000 units received. Vendor confirmed remaining 300 shipped separately, expected April 5. 2026-03-30 18:34:11.101225 +GR-3001 PO-3001 VND-003 2026-03-18 Sunil Verma Full delivery received. QC passed. 2026-03-30 18:34:11.102194 +GR-2002 PO-2002 VND-002 2026-03-18 Amit Kumar Full delivery received. 2026-03-30 18:34:11.103112 +GR-1002 PO-1002 VND-001 2026-03-18 Rajesh Sharma Partial delivery. 600 of 800 plates received. Remaining 200 delayed due to transport issues. 2026-03-30 18:34:11.104018 +\. + +COPY p2p_demo.gr_line_items (id, gr_number, product_code, quantity_received, condition) FROM stdin; +146 GR-2001 PRD-201 500 good +147 GR-1001 PRD-101 700 good +148 GR-3001 PRD-301 200 good +149 GR-2002 PRD-202 50 good +150 GR-1002 PRD-102 600 good +\. + +COPY p2p_demo.payments (payment_id, invoice_number, po_number, vendor_id, amount, payment_date, status, created_at) FROM stdin; +PAY-5001 INV-2026-00700 PO-2002 VND-002 75000.00 2026-03-10 completed 2026-03-30 18:34:11.10478 +PAY-5002 INV-2026-00800 PO-1002 VND-001 200000.00 2026-03-05 completed 2026-03-30 18:34:11.105142 +\. + +COPY p2p_demo.po_line_items (id, po_number, product_code, description, quantity, unit_price) FROM stdin; +175 PO-2001 PRD-201 A4 Paper Ream (500 sheets) 500 200.00 +176 PO-1001 PRD-101 Steel Rods 12mm 1000 1000.00 +177 PO-3001 PRD-301 Circuit Board Type-A 200 500.00 +178 PO-2002 PRD-202 Printer Ink Cartridge 50 1500.00 +179 PO-4001 PRD-401 Safety Helmet 300 150.00 +180 PO-1002 PRD-102 Steel Plates 5mm 800 1000.00 +\. + +COPY p2p_demo.purchase_orders (po_number, vendor_id, vendor_name, contract_id, order_date, expected_delivery, status, total_amount, created_at) FROM stdin; +PO-2001 VND-002 Reliance Office Supplies CNT-200 2026-02-15 2026-03-15 fully_received 100000.00 2026-03-30 18:34:11.094652 +PO-1001 VND-001 Tata Steel Ltd CNT-100 2026-02-15 2026-03-15 partially_received 1000000.00 2026-03-30 18:34:11.095959 +PO-3001 VND-003 Bharat Electronics CNT-300 2026-02-15 2026-03-15 fully_received 100000.00 2026-03-30 18:34:11.096847 +PO-2002 VND-002 Reliance Office Supplies CNT-200 2026-02-15 2026-03-15 fully_received 75000.00 2026-03-30 18:34:11.09772 +PO-4001 VND-004 Godrej Industrial CNT-400 2026-02-15 2026-03-15 open 45000.00 2026-03-30 18:34:11.098572 +PO-1002 VND-001 Tata Steel Ltd CNT-100 2026-02-15 2026-03-15 partially_received 800000.00 2026-03-30 18:34:11.099363 +\. + +ALTER TABLE ONLY p2p_demo.contract_line_items +ALTER TABLE ONLY p2p_demo.contracts +ALTER TABLE ONLY p2p_demo.goods_receipts +ALTER TABLE ONLY p2p_demo.gr_line_items +ALTER TABLE ONLY p2p_demo.payments +ALTER TABLE ONLY p2p_demo.po_line_items +ALTER TABLE ONLY p2p_demo.purchase_orders +ALTER TABLE ONLY p2p_demo.contract_line_items +ALTER TABLE ONLY p2p_demo.gr_line_items +ALTER TABLE ONLY p2p_demo.po_line_items \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..56d49cd --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2745 @@ +{ + "name": "p2p-dev", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "p2p-dev", + "version": "0.1.0", + "dependencies": { + "@tanstack/react-query": "^5.60.5", + "lucide-react": "^0.441.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.26.0" + }, + "devDependencies": { + "@types/react": "^18.3.5", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.1", + "autoprefixer": "^10.4.20", + "postcss": "^8.4.41", + "tailwindcss": "^3.4.10", + "typescript": "~5.5.4", + "vite": "^5.4.2" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@remix-run/router": { + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.2.tgz", + "integrity": "sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", + "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", + "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz", + "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz", + "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz", + "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz", + "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz", + "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz", + "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz", + "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz", + "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz", + "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz", + "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz", + "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz", + "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz", + "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz", + "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz", + "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz", + "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz", + "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz", + "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz", + "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz", + "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz", + "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz", + "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz", + "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tanstack/query-core": { + "version": "5.95.2", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.95.2.tgz", + "integrity": "sha512-o4T8vZHZET4Bib3jZ/tCW9/7080urD4c+0/AUaYVpIqOsr7y0reBc1oX3ttNaSW5mYyvZHctiQ/UOP2PfdmFEQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.95.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.95.2.tgz", + "integrity": "sha512-/wGkvLj/st5Ud1Q76KF1uFxScV7WeqN1slQx5280ycwAyYkIPGaRZAEgHxe3bjirSd5Zpwkj6zNcR4cqYni/ZA==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.95.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.28", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", + "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.4.27", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz", + "integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.1", + "caniuse-lite": "^1.0.30001774", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.12", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.12.tgz", + "integrity": "sha512-qyq26DxfY4awP2gIRXhhLWfwzwI+N5Nxk6iQi8EFizIaWIjqicQTE4sLnZZVdeKPRcVNoJOkkpfzoIYuvCKaIQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001782", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001782.tgz", + "integrity": "sha512-dZcaJLJeDMh4rELYFw1tvSn1bhZWYFOt468FcbHHxx/Z/dFidd1I6ciyFdi3iwfQCyOjqo9upF6lGQYtMiJWxw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.328", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.328.tgz", + "integrity": "sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w==", + "dev": true, + "license": "ISC" + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "0.441.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.441.0.tgz", + "integrity": "sha512-0vfExYtvSDhkC2lqg0zYVW1Uu9GsI4knuV9GP9by5z0Xhc4Zi5RejTxfz9LsjRmCyWVzHCJvxGKZWcRyvQCWVg==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "6.30.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.3.tgz", + "integrity": "sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.30.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.3.tgz", + "integrity": "sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.2", + "react-router": "6.30.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", + "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.60.1", + "@rollup/rollup-android-arm64": "4.60.1", + "@rollup/rollup-darwin-arm64": "4.60.1", + "@rollup/rollup-darwin-x64": "4.60.1", + "@rollup/rollup-freebsd-arm64": "4.60.1", + "@rollup/rollup-freebsd-x64": "4.60.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", + "@rollup/rollup-linux-arm-musleabihf": "4.60.1", + "@rollup/rollup-linux-arm64-gnu": "4.60.1", + "@rollup/rollup-linux-arm64-musl": "4.60.1", + "@rollup/rollup-linux-loong64-gnu": "4.60.1", + "@rollup/rollup-linux-loong64-musl": "4.60.1", + "@rollup/rollup-linux-ppc64-gnu": "4.60.1", + "@rollup/rollup-linux-ppc64-musl": "4.60.1", + "@rollup/rollup-linux-riscv64-gnu": "4.60.1", + "@rollup/rollup-linux-riscv64-musl": "4.60.1", + "@rollup/rollup-linux-s390x-gnu": "4.60.1", + "@rollup/rollup-linux-x64-gnu": "4.60.1", + "@rollup/rollup-linux-x64-musl": "4.60.1", + "@rollup/rollup-openbsd-x64": "4.60.1", + "@rollup/rollup-openharmony-arm64": "4.60.1", + "@rollup/rollup-win32-arm64-msvc": "4.60.1", + "@rollup/rollup-win32-ia32-msvc": "4.60.1", + "@rollup/rollup-win32-x64-gnu": "4.60.1", + "@rollup/rollup-win32-x64-msvc": "4.60.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..5326a85 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "p2p-dev", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "typecheck": "tsc -b", + "preview": "vite preview" + }, + "dependencies": { + "@tanstack/react-query": "^5.60.5", + "lucide-react": "^0.441.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.26.0" + }, + "devDependencies": { + "@types/react": "^18.3.5", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.1", + "autoprefixer": "^10.4.20", + "postcss": "^8.4.41", + "tailwindcss": "^3.4.10", + "typescript": "~5.5.4", + "vite": "^5.4.2" + } +} \ No newline at end of file diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..2e7af2b --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a11777cc471a4344702741ab1c8a588998b1311a GIT binary patch literal 3870 zcma);c{J4h9>;%nil|2-o+rCuEF-(I%-F}ijC~o(k~HKAkr0)!FCj~d>`RtpD?8b; zXOC1OD!V*IsqUwzbMF1)-gEDD=A573Z-&G7^LoAC9|WO7Xc0Cx1g^Zu0u_SjAPB3vGa^W|sj)80f#V0@M_CAZTIO(t--xg= z!sii`1giyH7EKL_+Wi0ab<)&E_0KD!3Rp2^HNB*K2@PHCs4PWSA32*-^7d{9nH2_E zmC{C*N*)(vEF1_aMamw2A{ZH5aIDqiabnFdJ|y0%aS|64E$`s2ccV~3lR!u<){eS` z#^Mx6o(iP1Ix%4dv`t@!&Za-K@mTm#vadc{0aWDV*_%EiGK7qMC_(`exc>-$Gb9~W!w_^{*pYRm~G zBN{nA;cm^w$VWg1O^^<6vY`1XCD|s_zv*g*5&V#wv&s#h$xlUilPe4U@I&UXZbL z0)%9Uj&@yd03n;!7do+bfixH^FeZ-Ema}s;DQX2gY+7g0s(9;`8GyvPY1*vxiF&|w z>!vA~GA<~JUqH}d;DfBSi^IT*#lrzXl$fNpq0_T1tA+`A$1?(gLb?e#0>UELvljtQ zK+*74m0jn&)5yk8mLBv;=@}c{t0ztT<v;Avck$S6D`Z)^c0(jiwKhQsn|LDRY&w(Fmi91I7H6S;b0XM{e zXp0~(T@k_r-!jkLwd1_Vre^v$G4|kh4}=Gi?$AaJ)3I+^m|Zyj#*?Kp@w(lQdJZf4 z#|IJW5z+S^e9@(6hW6N~{pj8|NO*>1)E=%?nNUAkmv~OY&ZV;m-%?pQ_11)hAr0oAwILrlsGawpxx4D43J&K=n+p3WLnlDsQ$b(9+4 z?mO^hmV^F8MV{4Lx>(Q=aHhQ1){0d*(e&s%G=i5rq3;t{JC zmgbn5Nkl)t@fPH$v;af26lyhH!k+#}_&aBK4baYPbZy$5aFx4}ka&qxl z$=Rh$W;U)>-=S-0=?7FH9dUAd2(q#4TCAHky!$^~;Dz^j|8_wuKc*YzfdAht@Q&ror?91Dm!N03=4=O!a)I*0q~p0g$Fm$pmr$ zb;wD;STDIi$@M%y1>p&_>%?UP($15gou_ue1u0!4(%81;qcIW8NyxFEvXpiJ|H4wz z*mFT(qVx1FKufG11hByuX%lPk4t#WZ{>8ka2efjY`~;AL6vWyQKpJun2nRiZYDij$ zP>4jQXPaP$UC$yIVgGa)jDV;F0l^n(V=HMRB5)20V7&r$jmk{UUIe zVjKroK}JAbD>B`2cwNQ&GDLx8{pg`7hbA~grk|W6LgiZ`8y`{Iq0i>t!3p2}MS6S+ zO_ruKyAElt)rdS>CtF7j{&6rP-#c=7evGMt7B6`7HG|-(WL`bDUAjyn+k$mx$CH;q2Dz4x;cPP$hW=`pFfLO)!jaCL@V2+F)So3}vg|%O*^T1j>C2lx zsURO-zIJC$^$g2byVbRIo^w>UxK}74^TqUiRR#7s_X$e)$6iYG1(PcW7un-va-S&u zHk9-6Zn&>T==A)lM^D~bk{&rFzCi35>UR!ZjQkdSiNX*-;l4z9j*7|q`TBl~Au`5& z+c)*8?#-tgUR$Zd%Q3bs96w6k7q@#tUn`5rj+r@_sAVVLqco|6O{ILX&U-&-cbVa3 zY?ngHR@%l{;`ri%H*0EhBWrGjv!LE4db?HEWb5mu*t@{kv|XwK8?npOshmzf=vZA@ zVSN9sL~!sn?r(AK)Q7Jk2(|M67Uy3I{eRy z_l&Y@A>;vjkWN5I2xvFFTLX0i+`{qz7C_@bo`ZUzDugfq4+>a3?1v%)O+YTd6@Ul7 zAfLfm=nhZ`)P~&v90$&UcF+yXm9sq!qCx3^9gzIcO|Y(js^Fj)Rvq>nQAHI92ap=P z10A4@prk+AGWCb`2)dQYFuR$|H6iDE8p}9a?#nV2}LBCoCf(Xi2@szia7#gY>b|l!-U`c}@ zLdhvQjc!BdLJvYvzzzngnw51yRYCqh4}$oRCy-z|v3Hc*d|?^Wj=l~18*E~*cR_kU z{XsxM1i{V*4GujHQ3DBpl2w4FgFR48Nma@HPgnyKoIEY-MqmMeY=I<%oG~l!f<+FN z1ZY^;10j4M4#HYXP zw5eJpA_y(>uLQ~OucgxDLuf}fVs272FaMxhn4xnDGIyLXnw>Xsd^J8XhcWIwIoQ9} z%FoSJTAGW(SRGwJwb=@pY7r$uQRK3Zd~XbxU)ts!4XsJrCycrWSI?e!IqwqIR8+Jh zlRjZ`UO1I!BtJR_2~7AbkbSm%XQqxEPkz6BTGWx8e}nQ=w7bZ|eVP4?*Tb!$(R)iC z9)&%bS*u(lXqzitAN)Oo=&Ytn>%Hzjc<5liuPi>zC_nw;Z0AE3Y$Jao_Q90R-gl~5 z_xAb2J%eArrC1CN4G$}-zVvCqF1;H;abAu6G*+PDHSYFx@Tdbfox*uEd3}BUyYY-l zTfEsOqsi#f9^FoLO;ChK<554qkri&Av~SIM*{fEYRE?vH7pTAOmu2pz3X?Wn*!ROX ztd54huAk&mFBemMooL33RV-*1f0Q3_(7hl$<#*|WF9P!;r;4_+X~k~uKEqdzZ$5Al zV63XN@)j$FN#cCD;ek1R#l zv%pGrhB~KWgoCj%GT?%{@@o(AJGt*PG#l3i>lhmb_twKH^EYvacVY-6bsCl5*^~L0 zonm@lk2UvvTKr2RS%}T>^~EYqdL1q4nD%0n&Xqr^cK^`J5W;lRRB^R-O8b&HENO||mo0xaD+S=I8RTlIfVgqN@SXDr2&-)we--K7w= zJVU8?Z+7k9dy;s;^gDkQa`0nz6N{T?(A&Iz)2!DEecLyRa&FI!id#5Z7B*O2=PsR0 zEvc|8{NS^)!d)MDX(97Xw}m&kEO@5jqRaDZ!+%`wYOI<23q|&js`&o4xvjP7D_xv@ z5hEwpsp{HezI9!~6O{~)lLR@oF7?J7i>1|5a~UuoN=q&6N}EJPV_GD`&M*v8Y`^2j zKII*d_@Fi$+i*YEW+Hbzn{iQk~yP z>7N{S4)r*!NwQ`(qcN#8SRQsNK6>{)X12nbF`*7#ecO7I)Q$uZsV+xS4E7aUn+U(K baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ literal 0 HcmV?d00001 diff --git a/public/zino-logo.svg b/public/zino-logo.svg new file mode 100644 index 0000000..76f11fa --- /dev/null +++ b/public/zino-logo.svg @@ -0,0 +1,9 @@ + + + + + + + + ZINO + diff --git a/public/zino.svg b/public/zino.svg new file mode 100644 index 0000000..662b67e --- /dev/null +++ b/public/zino.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/seed.sql b/seed.sql new file mode 100644 index 0000000..dc78efd --- /dev/null +++ b/seed.sql @@ -0,0 +1,47 @@ +-- App 20 Seed Script +-- Generated from local DB + + +-- Workflow +INSERT INTO tbl_appconfig_workflows (id, workflow_uid, version, app_id, content) VALUES (20109, 'wf_p2p_invoice_demo', '1', 20, '{"name": "P2P Invoice Validation", "states": [{"uid": "p2p-state-invoice-submitted", "name": "Invoice Submitted", "type": "STANDARD", "allowed_activities": ["p2p-act-request-clarification", "p2p-act-submit-recommendation"]}, {"uid": "p2p-state-ai-analysis", "name": "AI Analysis", "type": "STANDARD", "allowed_activities": ["p2p-act-request-clarification", "p2p-act-submit-recommendation"]}, {"uid": "p2p-state-awaiting-clarification", "name": "Awaiting Clarification", "type": "STANDARD", "allowed_activities": ["p2p-act-provide-clarification"]}, {"uid": "p2p-state-finance-review", "name": "Finance Review", "type": "STANDARD", "allowed_activities": ["p2p-act-approve-payment", "p2p-act-reject-payment", "p2p-act-hold-payment"]}, {"uid": "p2p-state-approved", "name": "Approved", "type": "END", "allowed_activities": []}, {"uid": "p2p-state-rejected", "name": "Rejected", "type": "END", "allowed_activities": []}, {"uid": "p2p-state-on-hold", "name": "On Hold", "type": "END", "allowed_activities": []}], "version": 1, "sg_rules": [], "activities": [{"uid": "p2p-act-submit-invoice", "name": "Submit Invoice", "type": "INIT"}, {"uid": "p2p-act-analyze-invoice", "name": "Analyze Invoice", "type": "NORMAL", "ai_confidence_threshold": 0.5}, {"uid": "p2p-act-request-clarification", "name": "Request Clarification", "type": "NORMAL"}, {"uid": "p2p-act-provide-clarification", "name": "Provide Clarification", "type": "NORMAL"}, {"uid": "p2p-act-submit-recommendation", "name": "Submit Recommendation", "type": "NORMAL"}, {"uid": "p2p-act-approve-payment", "name": "Approve Payment", "type": "NORMAL"}, {"uid": "p2p-act-reject-payment", "name": "Reject Payment", "type": "NORMAL"}, {"uid": "p2p-act-hold-payment", "name": "Hold Payment", "type": "NORMAL"}], "stage_gates": [], "transitions": [{"to_state_id": "p2p-state-invoice-submitted", "from_state_id": "", "by_activity_id": "p2p-act-submit-invoice", "transition_type": "INIT_TO_STATE"}, {"to_state_id": "p2p-state-awaiting-clarification", "from_state_id": "p2p-state-invoice-submitted", "by_activity_id": "p2p-act-request-clarification", "transition_type": "TO_STATE"}, {"to_state_id": "p2p-state-finance-review", "from_state_id": "p2p-state-invoice-submitted", "by_activity_id": "p2p-act-submit-recommendation", "transition_type": "TO_STATE"}, {"to_state_id": "p2p-state-awaiting-clarification", "from_state_id": "p2p-state-ai-analysis", "by_activity_id": "p2p-act-request-clarification", "transition_type": "TO_STATE"}, {"to_state_id": "p2p-state-finance-review", "from_state_id": "p2p-state-ai-analysis", "by_activity_id": "p2p-act-submit-recommendation", "transition_type": "TO_STATE"}, {"to_state_id": "p2p-state-ai-analysis", "from_state_id": "p2p-state-awaiting-clarification", "by_activity_id": "p2p-act-provide-clarification", "transition_type": "TO_STATE"}, {"to_state_id": "p2p-state-approved", "from_state_id": "p2p-state-finance-review", "by_activity_id": "p2p-act-approve-payment", "transition_type": "TO_STATE"}, {"to_state_id": "p2p-state-rejected", "from_state_id": "p2p-state-finance-review", "by_activity_id": "p2p-act-reject-payment", "transition_type": "TO_STATE"}, {"to_state_id": "p2p-state-on-hold", "from_state_id": "p2p-state-finance-review", "by_activity_id": "p2p-act-hold-payment", "transition_type": "TO_STATE"}], "workflow_id": "wf_p2p_invoice_demo", "activity_prefills": [], "activity_triggers": [{"nodes": [{"id": "a0a0a0a0-0000-4000-8000-000000093011", "name": "Start", "type": "start", "edges": [{"target": "a0a0a0a0-0000-4000-8000-000000093012", "source_handle": "output"}], "config": {}, "ui_config": null}, {"id": "a0a0a0a0-0000-4000-8000-000000093012", "name": "AI Employee", "type": "aiEmployee", "edges": [{"target": "a0a0a0a0-0000-4000-8000-000000093013", "source_handle": "output"}], "config": {"ai_user_id": "29100"}, "ui_config": null}, {"id": "a0a0a0a0-0000-4000-8000-000000093013", "name": "Complete", "type": "response", "edges": [], "config": {"message": "AI Employee task dispatched", "success": true, "status_code": 200}, "ui_config": null}], "trigger_uid": "trigger_p2p_submit", "activity_uid": "p2p-act-submit-invoice", "trigger_config": {}}, {"nodes": [{"id": "a0a0a0a0-0000-4000-8000-000000093041", "name": "Start", "type": "start", "edges": [{"target": "a0a0a0a0-0000-4000-8000-000000093042", "source_handle": "output"}], "config": {}, "ui_config": null}, {"id": "a0a0a0a0-0000-4000-8000-000000093042", "name": "AI Employee", "type": "aiEmployee", "edges": [{"target": "a0a0a0a0-0000-4000-8000-000000093043", "source_handle": "output"}], "config": {"ai_user_id": "29100"}, "ui_config": null}, {"id": "a0a0a0a0-0000-4000-8000-000000093043", "name": "Complete", "type": "response", "edges": [], "config": {"message": "AI Employee task dispatched", "success": true, "status_code": 200}, "ui_config": null}], "trigger_uid": "trigger_p2p_clarify", "activity_uid": "p2p-act-provide-clarification", "trigger_config": {}}], "activity_data_fields": [{"data_fields": [{"id": "approved_amount", "uid": "p2p-field-9423", "name": "Approved Amount", "type": "local", "data_type": "number", "mandatory": true}, {"id": "reviewer_notes", "uid": "p2p-field-9424", "name": "Reviewer Notes", "type": "local", "data_type": "text", "mandatory": false}], "activity_uid": "p2p-act-approve-payment", "activity_name": "Approve Payment"}, {"data_fields": [{"id": "rejection_reason", "uid": "p2p-field-9425", "name": "Rejection Reason", "type": "local", "data_type": "text", "mandatory": true}, {"id": "reviewer_notes", "uid": "p2p-field-9426", "name": "Reviewer Notes", "type": "local", "data_type": "text", "mandatory": false}], "activity_uid": "p2p-act-reject-payment", "activity_name": "Reject Payment"}, {"data_fields": [{"id": "hold_reason", "uid": "p2p-field-9427", "name": "Hold Reason", "type": "local", "data_type": "text", "mandatory": true}, {"id": "reviewer_notes", "uid": "p2p-field-9428", "name": "Reviewer Notes", "type": "local", "data_type": "text", "mandatory": false}], "activity_uid": "p2p-act-hold-payment", "activity_name": "Hold Payment"}, {"data_fields": [{"id": "vendor_id", "uid": "p2p-field-9401", "name": "Vendor ID", "type": "local", "data_type": "text", "mandatory": true}, {"id": "vendor_name", "uid": "p2p-field-9402", "name": "Vendor Name", "type": "local", "data_type": "text", "mandatory": true}, {"id": "invoice_number", "uid": "p2p-field-9403", "name": "Invoice Number", "type": "local", "data_type": "text", "mandatory": true}, {"id": "invoice_date", "uid": "p2p-field-9404", "name": "Invoice Date", "type": "local", "data_type": "date", "mandatory": true}, {"id": "po_number", "uid": "p2p-field-9405", "name": "PO Number", "type": "local", "data_type": "text", "mandatory": true}, {"id": "currency", "uid": "p2p-field-9406", "name": "Currency", "type": "local", "data_type": "text", "mandatory": false}, {"id": "total_amount", "uid": "p2p-field-9407", "name": "Total Amount", "type": "local", "data_type": "number", "mandatory": true}, {"id": "tax_amount", "uid": "p2p-field-9408", "name": "Tax Amount", "type": "local", "data_type": "number", "mandatory": false}, {"id": "payment_terms", "uid": "p2p-field-9409", "name": "Payment Terms", "type": "local", "data_type": "text", "mandatory": false}, {"id": "notes", "uid": "p2p-field-9410", "name": "Notes", "type": "local", "data_type": "text", "mandatory": false}], "activity_uid": "p2p-act-submit-invoice", "activity_name": "Submit Invoice"}, {"data_fields": [{"id": "target_department", "uid": "p2p-field-9411", "name": "Target Department", "type": "local", "data_type": "text", "mandatory": true}, {"id": "clarification_question", "uid": "p2p-field-9412", "name": "Question", "type": "local", "data_type": "text", "mandatory": true}, {"id": "clarification_context", "uid": "p2p-field-9413", "name": "Context", "type": "local", "data_type": "text", "mandatory": false}, {"id": "analysis_so_far", "uid": "p2p-field-9414", "name": "Analysis So Far", "type": "local", "data_type": "text", "mandatory": false}], "activity_uid": "p2p-act-request-clarification", "activity_name": "Request Clarification"}, {"data_fields": [{"id": "response_text", "uid": "p2p-field-9415", "name": "Response", "type": "local", "data_type": "text", "mandatory": true}, {"id": "confirmed_quantity", "uid": "p2p-field-9416", "name": "Confirmed Quantity", "type": "local", "data_type": "number", "mandatory": false}, {"id": "response_notes", "uid": "p2p-field-9417", "name": "Additional Notes", "type": "local", "data_type": "text", "mandatory": false}], "activity_uid": "p2p-act-provide-clarification", "activity_name": "Provide Clarification"}, {"data_fields": [{"id": "recommendation", "uid": "p2p-field-9418", "name": "Recommendation", "type": "local", "data_type": "text", "mandatory": true}, {"id": "recommended_amount", "uid": "p2p-field-9419", "name": "Recommended Payment Amount", "type": "local", "data_type": "number", "mandatory": false}, {"id": "match_summary", "uid": "p2p-field-9420", "name": "Match Summary", "type": "local", "data_type": "text", "mandatory": false}, {"id": "ai_reasoning", "uid": "p2p-field-9421", "name": "AI Reasoning", "type": "local", "data_type": "text", "mandatory": false}, {"id": "ai_confidence", "uid": "p2p-field-9422", "name": "AI Confidence", "type": "local", "data_type": "number", "mandatory": false}], "activity_uid": "p2p-act-submit-recommendation", "activity_name": "Submit Recommendation"}], "activity_permissions": [{"id": "p2p-act-submit-invoice", "allowed_roles": [{"role": "p2p_vendor", "positions": ""}], "allowed_groups": [], "dynamic_rbac_allowed": false, "only_roles_positions": false}, {"id": "p2p-act-analyze-invoice", "allowed_roles": [{"role": "p2p_ai_finance", "positions": ""}], "allowed_groups": [], "dynamic_rbac_allowed": false, "only_roles_positions": false}, {"id": "p2p-act-request-clarification", "allowed_roles": [{"role": "p2p_ai_finance", "positions": ""}], "allowed_groups": [], "dynamic_rbac_allowed": false, "only_roles_positions": false}, {"id": "p2p-act-provide-clarification", "allowed_roles": [{"role": "p2p_warehouse", "positions": ""}, {"role": "p2p_procurement", "positions": ""}, {"role": "p2p_ap_team", "positions": ""}], "allowed_groups": [], "dynamic_rbac_allowed": false, "only_roles_positions": false}, {"id": "p2p-act-submit-recommendation", "allowed_roles": [{"role": "p2p_ai_finance", "positions": ""}], "allowed_groups": [], "dynamic_rbac_allowed": false, "only_roles_positions": false}, {"id": "p2p-act-approve-payment", "allowed_roles": [{"role": "p2p_finance_reviewer", "positions": ""}], "allowed_groups": [], "dynamic_rbac_allowed": false, "only_roles_positions": false}, {"id": "p2p-act-reject-payment", "allowed_roles": [{"role": "p2p_finance_reviewer", "positions": ""}], "allowed_groups": [], "dynamic_rbac_allowed": false, "only_roles_positions": false}, {"id": "p2p-act-hold-payment", "allowed_roles": [{"role": "p2p_finance_reviewer", "positions": ""}], "allowed_groups": [], "dynamic_rbac_allowed": false, "only_roles_positions": false}], "workflow_data_fields": null}'::jsonb) ON CONFLICT (id) DO UPDATE SET content = EXCLUDED.content; + +-- Record Views +INSERT INTO tbl_appconfig_recordview (id, rv_uid, rv_description, workflow_uid, app_id, config) VALUES (20034, 'p2p-rv-all-invoices', 'All invoice instances across all states', 'wf_p2p_invoice_demo', 20, '{"fields": [{"type": "system-global", "data_type": "text", "field_key": "instance_id", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Instance ID"}, {"type": "system-global", "data_type": "text", "field_key": "current_state_name", "field_uid": "", "is_filter": true, "is_search": false, "activity_id": "SYSTEM", "output_label": "Current State"}, {"type": "local", "data_type": "text", "field_key": "vendor_name", "field_uid": "p2p-field-9401", "is_filter": true, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "Vendor"}, {"type": "local", "data_type": "text", "field_key": "invoice_number", "field_uid": "p2p-field-9403", "is_filter": false, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice #"}, {"type": "local", "data_type": "text", "field_key": "po_number", "field_uid": "p2p-field-9405", "is_filter": false, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "PO #"}, {"type": "local", "data_type": "number", "field_key": "total_amount", "field_uid": "p2p-field-9407", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Amount"}, {"type": "system-global", "data_type": "datetime", "field_key": "created_at", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Created"}]}'::jsonb) ON CONFLICT (id) DO UPDATE SET config = EXCLUDED.config; +INSERT INTO tbl_appconfig_recordview (id, rv_uid, rv_description, workflow_uid, app_id, config) VALUES (20035, 'p2p-rv-pending-clarifications', 'Invoices awaiting department clarification', 'wf_p2p_invoice_demo', 20, '{"fields": [{"type": "system-global", "data_type": "text", "field_key": "instance_id", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Instance ID"}, {"type": "local", "data_type": "text", "field_key": "vendor_name", "field_uid": "p2p-field-9402", "is_filter": false, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "Vendor"}, {"type": "local", "data_type": "text", "field_key": "invoice_number", "field_uid": "p2p-field-9403", "is_filter": false, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice #"}, {"type": "local", "data_type": "number", "field_key": "total_amount", "field_uid": "p2p-field-9407", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Amount"}, {"type": "local", "data_type": "text", "field_key": "target_department", "field_uid": "p2p-field-9411", "is_filter": true, "is_search": false, "activity_id": "p2p-act-request-clarification", "output_label": "Department"}, {"type": "system-global", "data_type": "datetime", "field_key": "created_at", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Created"}], "prefilters": {"logic": "AND", "conditions": [{"value": "Awaiting Clarification", "operator": "equals", "data_type": "text", "field_key": "current_state_name"}]}}'::jsonb) ON CONFLICT (id) DO UPDATE SET config = EXCLUDED.config; +INSERT INTO tbl_appconfig_recordview (id, rv_uid, rv_description, workflow_uid, app_id, config) VALUES (20037, 'p2p-rv-vendor-invoices', 'Vendor''s submitted invoices with status tracking', 'wf_p2p_invoice_demo', 20, '{"fields": [{"type": "system-global", "data_type": "text", "field_key": "instance_id", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Instance ID"}, {"type": "system-global", "data_type": "text", "field_key": "current_state_name", "field_uid": "", "is_filter": true, "is_search": false, "activity_id": "SYSTEM", "output_label": "Status"}, {"type": "local", "data_type": "text", "field_key": "invoice_number", "field_uid": "p2p-field-9403", "is_filter": false, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice #"}, {"type": "local", "data_type": "text", "field_key": "po_number", "field_uid": "p2p-field-9405", "is_filter": false, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "PO #"}, {"type": "local", "data_type": "number", "field_key": "total_amount", "field_uid": "p2p-field-9407", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Amount"}, {"type": "system-global", "data_type": "datetime", "field_key": "created_at", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Submitted"}]}'::jsonb) ON CONFLICT (id) DO UPDATE SET config = EXCLUDED.config; +INSERT INTO tbl_appconfig_recordview (id, rv_uid, rv_description, workflow_uid, app_id, config) VALUES (20036, 'p2p-rv-finance-review-queue', 'Invoices ready for finance review with AI recommendations', 'wf_p2p_invoice_demo', 20, '{"fields": [{"type": "system-global", "data_type": "text", "field_key": "instance_id", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Instance ID"}, {"type": "local", "data_type": "text", "field_key": "vendor_name", "field_uid": "p2p-field-9402", "is_filter": false, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "Vendor"}, {"type": "local", "data_type": "text", "field_key": "invoice_number", "field_uid": "p2p-field-9403", "is_filter": false, "is_search": true, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice #"}, {"type": "local", "data_type": "number", "field_key": "total_amount", "field_uid": "p2p-field-9407", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Amount"}, {"type": "local", "data_type": "text", "field_key": "recommendation", "field_uid": "p2p-field-9418", "is_filter": true, "is_search": false, "activity_id": "p2p-act-submit-recommendation", "output_label": "AI Recommendation"}, {"type": "local", "data_type": "number", "field_key": "recommended_amount", "field_uid": "p2p-field-9419", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-recommendation", "output_label": "Recommended Amt"}, {"type": "system-global", "data_type": "datetime", "field_key": "created_at", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Created"}], "prefilters": {"logic": "AND", "conditions": [{"value": "Finance Review", "operator": "equals", "data_type": "text", "field_key": "current_state_name"}]}}'::jsonb) ON CONFLICT (id) DO UPDATE SET config = EXCLUDED.config; + +-- Detail Views +INSERT INTO tbl_appconfig_detailview (id, dv_uid, dv_description, workflow_uid, app_id, config) VALUES (20014, 'p2p-dv-clarification-detail', 'AI question and context for department response', 'wf_p2p_invoice_demo', 20, '{"fields": [{"type": "system-global", "data_type": "text", "field_key": "instance_id", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Instance ID"}, {"type": "local", "data_type": "text", "field_key": "vendor_name", "field_uid": "p2p-field-9402", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Vendor"}, {"type": "local", "data_type": "text", "field_key": "invoice_number", "field_uid": "p2p-field-9403", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice #"}, {"type": "local", "data_type": "text", "field_key": "po_number", "field_uid": "p2p-field-9405", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "PO #"}, {"type": "local", "data_type": "number", "field_key": "total_amount", "field_uid": "p2p-field-9407", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Amount"}, {"type": "local", "data_type": "text", "field_key": "target_department", "field_uid": "p2p-field-9411", "is_filter": false, "is_search": false, "activity_id": "p2p-act-request-clarification", "output_label": "Target Department"}, {"type": "local", "data_type": "text", "field_key": "clarification_question", "field_uid": "p2p-field-9412", "is_filter": false, "is_search": false, "activity_id": "p2p-act-request-clarification", "output_label": "AI Question"}, {"type": "local", "data_type": "text", "field_key": "clarification_context", "field_uid": "p2p-field-9413", "is_filter": false, "is_search": false, "activity_id": "p2p-act-request-clarification", "output_label": "Context"}, {"type": "local", "data_type": "text", "field_key": "analysis_so_far", "field_uid": "p2p-field-9414", "is_filter": false, "is_search": false, "activity_id": "p2p-act-request-clarification", "output_label": "Analysis So Far"}]}'::jsonb) ON CONFLICT (id) DO UPDATE SET config = EXCLUDED.config; +INSERT INTO tbl_appconfig_detailview (id, dv_uid, dv_description, workflow_uid, app_id, config) VALUES (20015, 'p2p-dv-finance-review-detail', 'AI recommendation with full decision trail for finance reviewer', 'wf_p2p_invoice_demo', 20, '{"fields": [{"type": "system-global", "data_type": "text", "field_key": "instance_id", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Instance ID"}, {"type": "system-global", "data_type": "text", "field_key": "current_state_name", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Status"}, {"type": "local", "data_type": "text", "field_key": "vendor_name", "field_uid": "p2p-field-9402", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Vendor"}, {"type": "local", "data_type": "text", "field_key": "invoice_number", "field_uid": "p2p-field-9403", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice #"}, {"type": "local", "data_type": "text", "field_key": "po_number", "field_uid": "p2p-field-9405", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "PO #"}, {"type": "local", "data_type": "number", "field_key": "total_amount", "field_uid": "p2p-field-9407", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice Amount"}, {"type": "local", "data_type": "number", "field_key": "tax_amount", "field_uid": "p2p-field-9408", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Tax"}, {"type": "local", "data_type": "text", "field_key": "recommendation", "field_uid": "p2p-field-9418", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-recommendation", "output_label": "AI Recommendation"}, {"type": "local", "data_type": "number", "field_key": "recommended_amount", "field_uid": "p2p-field-9419", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-recommendation", "output_label": "Recommended Amount"}, {"type": "local", "data_type": "text", "field_key": "match_summary", "field_uid": "p2p-field-9420", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-recommendation", "output_label": "Match Summary"}, {"type": "local", "data_type": "text", "field_key": "ai_reasoning", "field_uid": "p2p-field-9421", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-recommendation", "output_label": "AI Reasoning"}, {"type": "local", "data_type": "number", "field_key": "ai_confidence", "field_uid": "p2p-field-9422", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-recommendation", "output_label": "AI Confidence"}]}'::jsonb) ON CONFLICT (id) DO UPDATE SET config = EXCLUDED.config; +INSERT INTO tbl_appconfig_detailview (id, dv_uid, dv_description, workflow_uid, app_id, config) VALUES (20013, 'p2p-dv-invoice-detail', 'Full invoice detail with AI analysis trail', 'wf_p2p_invoice_demo', 20, '{"fields": [{"type": "system-global", "data_type": "text", "field_key": "instance_id", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Instance ID"}, {"type": "system-global", "data_type": "text", "field_key": "current_state_name", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Status"}, {"type": "system-global", "data_type": "datetime", "field_key": "created_at", "field_uid": "", "is_filter": false, "is_search": false, "activity_id": "SYSTEM", "output_label": "Created"}, {"type": "local", "data_type": "text", "field_key": "vendor_id", "field_uid": "p2p-field-9401", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Vendor ID"}, {"type": "local", "data_type": "text", "field_key": "vendor_name", "field_uid": "p2p-field-9402", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Vendor Name"}, {"type": "local", "data_type": "text", "field_key": "invoice_number", "field_uid": "p2p-field-9403", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice Number"}, {"type": "local", "data_type": "date", "field_key": "invoice_date", "field_uid": "p2p-field-9404", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Invoice Date"}, {"type": "local", "data_type": "text", "field_key": "po_number", "field_uid": "p2p-field-9405", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "PO Number"}, {"type": "local", "data_type": "number", "field_key": "total_amount", "field_uid": "p2p-field-9407", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Total Amount"}, {"type": "local", "data_type": "number", "field_key": "tax_amount", "field_uid": "p2p-field-9408", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Tax Amount"}, {"type": "local", "data_type": "text", "field_key": "payment_terms", "field_uid": "p2p-field-9409", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Payment Terms"}, {"type": "local", "data_type": "text", "field_key": "notes", "field_uid": "p2p-field-9410", "is_filter": false, "is_search": false, "activity_id": "p2p-act-submit-invoice", "output_label": "Vendor Notes"}]}'::jsonb) ON CONFLICT (id) DO UPDATE SET config = EXCLUDED.config; + +-- Screens +INSERT INTO tbl_appconfig_screens (id, source_screen_id, app_id, screen_name, device, description, layout, permissions) VALUES (20027, 29643, 20, 'P2P - Finance Review Detail', 'desktop', 'P2P - Finance Review Detail', '[{"type": "element", "style": {"width": "100%", "padding": "16px"}, "config": {"type": "detailsview", "view_id": "29613"}}]'::jsonb, NULL) ON CONFLICT (id) DO UPDATE SET layout = EXCLUDED.layout; +INSERT INTO tbl_appconfig_screens (id, source_screen_id, app_id, screen_name, device, description, layout, permissions) VALUES (20010, 29631, 20, 'P2P - My Invoices', 'desktop', 'P2P - My Invoices', '[{"type": "element", "style": {"marginBottom": "16px"}, "config": {"icon": "add", "name": "+ Submit New Invoice", "type": "button", "params": {"workflow_id": "wf_p2p_invoice_demo", "activity_id_init": "p2p-act-submit-invoice"}, "action_end": [{"type": "refresh_page"}], "job_template": "start_state_machine"}, "classes": ["z-btn-primary"]}, {"type": "element", "style": {"width": "100%"}, "config": {"type": "recordsview", "view_id": "29601"}}]'::jsonb, NULL) ON CONFLICT (id) DO UPDATE SET layout = EXCLUDED.layout; +INSERT INTO tbl_appconfig_screens (id, source_screen_id, app_id, screen_name, device, description, layout, permissions) VALUES (20011, 29632, 20, 'P2P - Pending Clarifications', 'desktop', 'P2P - Pending Clarifications', '[{"type": "element", "style": {"width": "100%"}, "config": {"type": "recordsview", "view_id": "29602"}}]'::jsonb, NULL) ON CONFLICT (id) DO UPDATE SET layout = EXCLUDED.layout; +INSERT INTO tbl_appconfig_screens (id, source_screen_id, app_id, screen_name, device, description, layout, permissions) VALUES (20012, 29633, 20, 'P2P - Finance Review', 'desktop', 'P2P - Finance Review', '[{"type": "element", "style": {"width": "100%"}, "config": {"type": "recordsview", "view_id": "29603"}}]'::jsonb, NULL) ON CONFLICT (id) DO UPDATE SET layout = EXCLUDED.layout; +INSERT INTO tbl_appconfig_screens (id, source_screen_id, app_id, screen_name, device, description, layout, permissions) VALUES (20013, 29634, 20, 'P2P - All Invoices', 'desktop', 'P2P - All Invoices', '[{"type": "element", "style": {"width": "100%"}, "config": {"type": "recordsview", "view_id": "29604"}}]'::jsonb, NULL) ON CONFLICT (id) DO UPDATE SET layout = EXCLUDED.layout; +INSERT INTO tbl_appconfig_screens (id, source_screen_id, app_id, screen_name, device, description, layout, permissions) VALUES (20025, 29641, 20, 'P2P - Invoice Detail', 'desktop', 'P2P - Invoice Detail', '[{"type": "element", "style": {"width": "100%", "padding": "16px"}, "config": {"type": "detailsview", "view_id": "29611"}}]'::jsonb, NULL) ON CONFLICT (id) DO UPDATE SET layout = EXCLUDED.layout; +INSERT INTO tbl_appconfig_screens (id, source_screen_id, app_id, screen_name, device, description, layout, permissions) VALUES (20026, 29642, 20, 'P2P - Clarification Detail', 'desktop', 'P2P - Clarification Detail', '[{"type": "element", "style": {"width": "100%", "padding": "16px"}, "config": {"type": "detailsview", "view_id": "29612"}}]'::jsonb, NULL) ON CONFLICT (id) DO UPDATE SET layout = EXCLUDED.layout; + +-- RV Screens +INSERT INTO tbl_appconfig_rv_screens (id, source_screen_id, app_id, screen_name, device, description, layout, rv_template_id) VALUES (20001, 29601, 20, 'Vendor - My Invoices', 'desktop', 'Vendor - My Invoices', '[{"type": "element", "style": {}, "config": {"type": "rv_table", "columns": [{"id": "current_state_name", "display": "Status", "key_name": "current_state_name", "data_type": "text"}, {"id": "invoice_number", "display": "Invoice #", "key_name": "invoice_number", "data_type": "text"}, {"id": "po_number", "display": "PO #", "key_name": "po_number", "data_type": "text"}, {"id": "total_amount", "display": "Amount", "key_name": "total_amount", "data_type": "number"}, {"id": "created_at", "display": "Submitted", "key_name": "created_at", "data_type": "datetime"}], "view_id": "29601", "on_row_click": {"screen_id": "29641", "job_template": "navigate_to_screen"}}}]'::jsonb, 29504) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_rv_screens (id, source_screen_id, app_id, screen_name, device, description, layout, rv_template_id) VALUES (20002, 29602, 20, 'Department - Pending Clarifications', 'desktop', 'Department - Pending Clarifications', '[{"type": "element", "style": {}, "config": {"type": "rv_table", "columns": [{"id": "vendor_name", "display": "Vendor", "key_name": "vendor_name", "data_type": "text"}, {"id": "invoice_number", "display": "Invoice #", "key_name": "invoice_number", "data_type": "text"}, {"id": "total_amount", "display": "Amount", "key_name": "total_amount", "data_type": "number"}, {"id": "target_department", "display": "Department", "key_name": "target_department", "data_type": "text"}, {"id": "created_at", "display": "Created", "key_name": "created_at", "data_type": "datetime"}], "view_id": "29602", "on_row_click": {"screen_id": "29642", "job_template": "navigate_to_screen"}}}]'::jsonb, 29502) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_rv_screens (id, source_screen_id, app_id, screen_name, device, description, layout, rv_template_id) VALUES (20003, 29603, 20, 'Finance - Review Queue', 'desktop', 'Finance - Review Queue', '[{"type": "element", "style": {}, "config": {"type": "rv_table", "columns": [{"id": "vendor_name", "display": "Vendor", "key_name": "vendor_name", "data_type": "text"}, {"id": "invoice_number", "display": "Invoice #", "key_name": "invoice_number", "data_type": "text"}, {"id": "total_amount", "display": "Amount", "key_name": "total_amount", "data_type": "number"}, {"id": "recommendation", "display": "AI Recommendation", "key_name": "recommendation", "data_type": "text"}, {"id": "recommended_amount", "display": "Recommended Amt", "key_name": "recommended_amount", "data_type": "number"}, {"id": "created_at", "display": "Created", "key_name": "created_at", "data_type": "datetime"}], "view_id": "29603", "on_row_click": {"screen_id": "29643", "job_template": "navigate_to_screen"}}}]'::jsonb, 29503) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_rv_screens (id, source_screen_id, app_id, screen_name, device, description, layout, rv_template_id) VALUES (20004, 29604, 20, 'Admin - All Invoices', 'desktop', 'Admin - All Invoices', '[{"type": "element", "style": {}, "config": {"type": "rv_table", "columns": [{"id": "current_state_name", "display": "Status", "key_name": "current_state_name", "data_type": "text"}, {"id": "vendor_name", "display": "Vendor", "key_name": "vendor_name", "data_type": "text"}, {"id": "invoice_number", "display": "Invoice #", "key_name": "invoice_number", "data_type": "text"}, {"id": "po_number", "display": "PO #", "key_name": "po_number", "data_type": "text"}, {"id": "total_amount", "display": "Amount", "key_name": "total_amount", "data_type": "number"}, {"id": "created_at", "display": "Created", "key_name": "created_at", "data_type": "datetime"}], "view_id": "29604", "on_row_click": {"screen_id": "29641", "job_template": "navigate_to_screen"}}}]'::jsonb, 29501) ON CONFLICT (id) DO NOTHING; + +-- DV Screens +INSERT INTO tbl_appconfig_dv_screens (id, source_screen_id, app_id, screen_name, device, description, layout, dv_template_id) VALUES (20004, 29611, 20, 'Invoice Detail View', 'desktop', 'Invoice Detail View', '[{"type": "element", "style": {"fontSize": "16px", "marginTop": "20px", "fontWeight": "700", "borderBottom": "1px solid #e2e8f0", "marginBottom": "8px", "paddingBottom": "6px"}, "config": {"name": "Invoice Details", "type": "label"}, "classes": []}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Status", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Status", "keyName": "current_state_name"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Vendor", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Vendor", "keyName": "vendor_name"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Invoice Number", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Invoice #", "keyName": "invoice_number"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Invoice Date", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Date", "keyName": "invoice_date"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "PO Number", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "PO #", "keyName": "po_number"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Total Amount", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Amount", "keyName": "total_amount"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Tax Amount", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Tax", "keyName": "tax_amount"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Payment Terms", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Terms", "keyName": "payment_terms"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Vendor Notes", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Notes", "keyName": "notes"}}}]'::jsonb, 29511) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_dv_screens (id, source_screen_id, app_id, screen_name, device, description, layout, dv_template_id) VALUES (20006, 29613, 20, 'Finance Review Detail View', 'desktop', 'Finance Review Detail View', '[{"type": "element", "style": {"fontSize": "16px", "marginTop": "20px", "fontWeight": "700", "borderBottom": "1px solid #e2e8f0", "marginBottom": "8px", "paddingBottom": "6px"}, "config": {"name": "Invoice Details", "type": "label"}, "classes": []}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Status", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Status", "keyName": "current_state_name"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Vendor", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Vendor", "keyName": "vendor_name"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Invoice Number", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Invoice #", "keyName": "invoice_number"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "PO Number", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "PO #", "keyName": "po_number"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Invoice Amount", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Amount", "keyName": "total_amount"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Tax", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Tax", "keyName": "tax_amount"}}}, {"type": "element", "style": {"fontSize": "16px", "marginTop": "20px", "fontWeight": "700", "borderBottom": "1px solid #e2e8f0", "marginBottom": "8px", "paddingBottom": "6px"}, "config": {"name": "AI Recommendation", "type": "label"}, "classes": []}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Recommendation", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Recommendation", "keyName": "recommendation"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Recommended Amount", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Amount", "keyName": "recommended_amount"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Match Summary", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Match Summary", "keyName": "match_summary"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "AI Reasoning", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Reasoning", "keyName": "ai_reasoning"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "AI Confidence", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Confidence", "keyName": "ai_confidence"}}}, {"type": "element", "style": {"display": "inline-block", "marginTop": "20px", "marginRight": "8px"}, "config": {"icon": "check_circle", "name": "Approve Payment", "type": "button", "params": {"activity_id": "p2p-act-approve-payment", "workflow_id": "wf_p2p_invoice_demo"}, "action_end": [{"type": "refresh_page"}], "job_template": "perform_activity"}, "classes": ["z-btn-primary"]}, {"type": "element", "style": {"display": "inline-block", "marginTop": "20px", "marginRight": "8px"}, "config": {"icon": "cancel", "name": "Reject Payment", "type": "button", "params": {"activity_id": "p2p-act-reject-payment", "workflow_id": "wf_p2p_invoice_demo"}, "action_end": [{"type": "refresh_page"}], "job_template": "perform_activity"}, "classes": ["z-btn-outline"]}, {"type": "element", "style": {"display": "inline-block", "marginTop": "20px"}, "config": {"icon": "pause_circle", "name": "Hold Payment", "type": "button", "params": {"activity_id": "p2p-act-hold-payment", "workflow_id": "wf_p2p_invoice_demo"}, "action_end": [{"type": "refresh_page"}], "job_template": "perform_activity"}, "classes": ["z-btn-outline"]}]'::jsonb, 29513) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_dv_screens (id, source_screen_id, app_id, screen_name, device, description, layout, dv_template_id) VALUES (20005, 29612, 20, 'Clarification Detail View', 'desktop', 'Clarification Detail View', '[{"type": "element", "style": {"fontSize": "16px", "marginTop": "20px", "fontWeight": "700", "borderBottom": "1px solid #e2e8f0", "marginBottom": "8px", "paddingBottom": "6px"}, "config": {"name": "Invoice Summary", "type": "label"}, "classes": []}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Vendor", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Vendor", "keyName": "vendor_name"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Invoice Number", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Invoice #", "keyName": "invoice_number"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "PO Number", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "PO #", "keyName": "po_number"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Amount", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Amount", "keyName": "total_amount"}}}, {"type": "element", "style": {"fontSize": "16px", "marginTop": "20px", "fontWeight": "700", "borderBottom": "1px solid #e2e8f0", "marginBottom": "8px", "paddingBottom": "6px"}, "config": {"name": "AI Clarification Request", "type": "label"}, "classes": []}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Target Department", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Department", "keyName": "target_department"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Question from AI", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Question", "keyName": "clarification_question"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Context", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Context", "keyName": "clarification_context"}}}, {"type": "element", "style": {"color": "#64748b", "fontSize": "13px", "marginTop": "12px", "fontWeight": "600"}, "config": {"name": "Analysis So Far", "type": "label"}, "classes": []}, {"type": "element", "style": {"marginBottom": "4px"}, "config": {"type": "field", "field": {"label": "Analysis", "keyName": "analysis_so_far"}}}, {"type": "element", "style": {"marginTop": "20px"}, "config": {"icon": "reply", "name": "Respond to Clarification", "type": "button", "params": {"activity_id": "p2p-act-provide-clarification", "workflow_id": "wf_p2p_invoice_demo"}, "action_end": [{"type": "refresh_page"}], "job_template": "perform_activity"}, "classes": ["z-btn-primary"]}]'::jsonb, 29512) ON CONFLICT (id) DO NOTHING; + +-- Form Screens +INSERT INTO tbl_appconfig_form_screens (id, source_form_id, activity_uid, device_type, layout, grid_config, app_id) VALUES (20136, 20094, 'p2p-act-submit-invoice', 'desktop', '[]'::jsonb, '[{"h": 1, "i": "p2p-field-9401", "w": 6, "x": 0, "y": 0}, {"h": 1, "i": "p2p-field-9402", "w": 6, "x": 6, "y": 0}, {"h": 1, "i": "p2p-field-9403", "w": 6, "x": 0, "y": 1}, {"h": 1, "i": "p2p-field-9404", "w": 6, "x": 6, "y": 1}, {"h": 1, "i": "p2p-field-9405", "w": 6, "x": 0, "y": 2}, {"h": 1, "i": "p2p-field-9406", "w": 6, "x": 6, "y": 2}, {"h": 1, "i": "p2p-field-9407", "w": 6, "x": 0, "y": 3}, {"h": 1, "i": "p2p-field-9408", "w": 6, "x": 6, "y": 3}, {"h": 1, "i": "p2p-field-9409", "w": 6, "x": 0, "y": 4}, {"h": 1, "i": "p2p-field-9410", "w": 6, "x": 6, "y": 4}]'::jsonb, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_form_screens (id, source_form_id, activity_uid, device_type, layout, grid_config, app_id) VALUES (20137, 20095, 'p2p-act-provide-clarification', 'desktop', '[]'::jsonb, '[{"h": 1, "i": "p2p-field-9415", "w": 12, "x": 0, "y": 0}, {"h": 1, "i": "p2p-field-9416", "w": 12, "x": 0, "y": 1}, {"h": 1, "i": "p2p-field-9417", "w": 12, "x": 0, "y": 2}]'::jsonb, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_form_screens (id, source_form_id, activity_uid, device_type, layout, grid_config, app_id) VALUES (20138, 20096, 'p2p-act-approve-payment', 'desktop', '[]'::jsonb, '[{"h": 1, "i": "p2p-field-9423", "w": 6, "x": 0, "y": 0}, {"h": 1, "i": "p2p-field-9424", "w": 6, "x": 6, "y": 0}]'::jsonb, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_form_screens (id, source_form_id, activity_uid, device_type, layout, grid_config, app_id) VALUES (20139, 20097, 'p2p-act-reject-payment', 'desktop', '[]'::jsonb, '[{"h": 1, "i": "p2p-field-9425", "w": 12, "x": 0, "y": 0}, {"h": 1, "i": "p2p-field-9426", "w": 12, "x": 0, "y": 1}]'::jsonb, 20) ON CONFLICT (id) DO NOTHING; +INSERT INTO tbl_appconfig_form_screens (id, source_form_id, activity_uid, device_type, layout, grid_config, app_id) VALUES (20140, 20098, 'p2p-act-hold-payment', 'desktop', '[]'::jsonb, '[{"h": 1, "i": "p2p-field-9427", "w": 12, "x": 0, "y": 0}, {"h": 1, "i": "p2p-field-9428", "w": 12, "x": 0, "y": 1}]'::jsonb, 20) ON CONFLICT (id) DO NOTHING; + +-- Header Config +INSERT INTO tbl_appconfig_header_config (id, app_id, device_type, config) VALUES (20001, 20, 'desktop', '{"slots": {"left": ["logo", "nav"], "right": ["profile"], "center": []}, "layout": {"type": "classic", "height": "56px", "position": "sticky", "full_width": true}, "components": {"nav": {"items": [{"id": "nav_vendor", "icon": "receipt_long", "type": "screen", "label": "My Invoices", "screen_id": 29631}, {"id": "nav_clarifications", "icon": "help_outline", "type": "screen", "label": "Pending Clarifications", "screen_id": 29632}, {"id": "nav_finance", "icon": "account_balance", "type": "screen", "label": "Finance Review", "screen_id": 29633}, {"id": "nav_all", "icon": "list_alt", "type": "screen", "label": "All Invoices", "screen_id": 29634}]}, "logo": {"text": "P2P Invoice System", "display_type": "text"}, "profile": {"shape": "circle", "show_name": true}}}'::jsonb) ON CONFLICT (id) DO UPDATE SET config = EXCLUDED.config; diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..4a187b0 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,37 @@ +import { Routes, Route, Navigate } from 'react-router-dom' +import { ProtectedRoute } from './components/ProtectedRoute' +import Login from './pages/Login' +import AppShell from './components/AppShell' + +export default function App() { + return ( + + } /> + + + + } + /> + + + + } + /> + + + + } + /> + } /> + + ) +} diff --git a/src/api/viewService.ts b/src/api/viewService.ts new file mode 100644 index 0000000..0dcf335 --- /dev/null +++ b/src/api/viewService.ts @@ -0,0 +1,422 @@ +import { APP_ID } from "../config"; + +const TOKEN_KEY = "zino_token"; + +function baseUrl(): string { + return (import.meta.env.VITE_ZINO_API_URL || "").replace(/\/+$/, ""); +} + +function headers(): Record { + const h: Record = { "Content-Type": "application/json" }; + const token = localStorage.getItem(TOKEN_KEY); + if (token) h["Authorization"] = `Bearer ${token}`; + return h; +} + +async function request(method: string, path: string, body?: unknown): Promise { + const res = await fetch(`${baseUrl()}${path}`, { + method, + headers: headers(), + body: body ? JSON.stringify(body) : undefined, + }); + if (res.status === 401) { + localStorage.removeItem(TOKEN_KEY); + localStorage.removeItem("zino_user"); + window.location.href = `${import.meta.env.BASE_URL}login`; + throw new Error("Unauthorized"); + } + if (!res.ok) { + let msg = res.statusText; + try { const e = await res.json(); if (e.error) msg = e.error; } catch {} + throw new Error(msg); + } + if (res.status === 204) return undefined as T; + return res.json() as Promise; +} + +// --------------------------------------------------------------------------- +// Header +// --------------------------------------------------------------------------- + +export interface HeaderConfig { + slots: { left: string[]; right: string[]; center: string[] }; + layout: { type: string; height: string; position: string; full_width: boolean }; + components: { + nav?: { items: NavItem[] }; + logo?: { text?: string; image_url?: string; display_type: string }; + profile?: { shape: string; show_name: boolean }; + }; +} + +export interface NavItem { + id: string; + icon: string; + type: string; + label: string; + screen_uuid: string; +} + +export async function getHeaderConfig(deviceType = "desktop"): Promise { + const raw = await request("GET", `/app/${APP_ID}/view/header/${deviceType}`); + return raw.config ?? raw; +} + +// --------------------------------------------------------------------------- +// Screens +// --------------------------------------------------------------------------- + +export interface ScreenListItem { + id: number; + source_screen_id: number; + screen_name: string; + device: string; + description: string; +} + +export interface ScreenLayout { + id: number; + source_screen_id: number; + screen_name: string; + layout: LayoutElement[]; +} + +export interface LayoutElement { + type: string; + style?: Record; + config: Record; + classes?: string[]; +} + +export function getScreens(deviceType = "desktop"): Promise { + return request("GET", `/app/${APP_ID}/view/screens?device_type=${deviceType}`); +} + +export function getScreen(idOrUuid: number | string): Promise { + return request("GET", `/app/${APP_ID}/view/screens/${idOrUuid}`); +} + +// --------------------------------------------------------------------------- +// RV Screens +// --------------------------------------------------------------------------- + +export interface RVScreen { + id: number; + source_screen_id: number; + screen_name: string; + rv_template_uid: string; + layout?: any; +} + +// Accepts either the numeric source_screen_id OR the source_uuid — both +// are accepted by the view-service's rv-screens endpoint. +export function getRVScreen(idOrUuid: number | string): Promise { + return request("GET", `/app/${APP_ID}/view/rv-screens/${idOrUuid}`); +} + +// --------------------------------------------------------------------------- +// Record View (POST-based) +// --------------------------------------------------------------------------- + +export interface SearchQuery { + page?: number; + limit?: number; + sort_by?: string; + sort_dir?: "asc" | "desc"; + search?: string; + filters?: Array<{ field_key: string; value: string; data_type?: string }>; +} + +export interface RecordViewField { + field_key: string; + output_label: string; + data_type: string; + is_filter: boolean; + is_search: boolean; + type?: string; + activity_id?: string; +} + +export interface TileValue { + tile_uid: string; + key: string; + value: unknown; +} + +export interface ChartDataRow { + dimension: unknown; + series?: string; + value: unknown; +} + +export interface ChartDataResponse { + chart_uid: string; + key: string; + rows: ChartDataRow[]; +} + +export interface RecordViewResponse { + config: { fields: RecordViewField[] }; + data: Record[]; + pagination?: { + page: number; + limit: number; + total_count: number; + total_pages: number; + }; + tile_values?: TileValue[]; + chart_data?: ChartDataResponse[]; +} + +export function getRecordView( + rvTemplateUid: string, + rvScreenId: string | number, + query: SearchQuery = {}, +): Promise { + return request("POST", `/app/${APP_ID}/view/recordview`, { + rv_template_uid: rvTemplateUid, + rv_screen_id: String(rvScreenId), + search_query: { + page: query.page || 1, + limit: query.limit || 50, + sort_by: query.sort_by || "", + sort_dir: query.sort_dir || "desc", + search: query.search || "", + filters: query.filters || [], + }, + }); +} + +export function getRecordViewLegacy( + rvUid: string, + query: SearchQuery = {}, +): Promise { + const qs = new URLSearchParams(); + qs.set("rv_id", rvUid); + if (query.page) qs.set("page", String(query.page)); + if (query.limit) qs.set("limit", String(query.limit)); + if (query.sort_by) qs.set("sort_by", query.sort_by); + if (query.sort_dir) qs.set("sort_dir", query.sort_dir); + if (query.search) qs.set("search", query.search); + if (query.filters) { + for (const f of query.filters) { + qs.set(`filter.${f.field_key}`, f.value); + } + } + return request("GET", `/recordview?${qs.toString()}`); +} + +// --------------------------------------------------------------------------- +// DV Screens +// --------------------------------------------------------------------------- + +export interface DVScreen { + id: number; + source_screen_id: number; + screen_name: string; + dv_template_uid: string; + layout?: any; +} + +export function getDVScreen(idOrUuid: number | string): Promise { + return request("GET", `/app/${APP_ID}/view/dv-screens/${idOrUuid}`); +} + +// --------------------------------------------------------------------------- +// Detail View +// --------------------------------------------------------------------------- + +export interface DetailViewResponse { + config: { fields: Array<{ field_key: string; output_label: string; data_type: string }> }; + data: Record; +} + +export function getDetailView(dvSourceIdOrUid: number | string, instanceId: string): Promise { + return request( + "GET", + `/app/${APP_ID}/view/detailview/${encodeURIComponent(String(dvSourceIdOrUid))}?instance_id=${encodeURIComponent(instanceId)}`, + ); +} + +export function getDetailViewLegacy(dvUid: string, instanceId: string): Promise { + return request( + "GET", + `/detailview?dv_id=${encodeURIComponent(dvUid)}&instance_id=${encodeURIComponent(instanceId)}`, + ); +} + +// --------------------------------------------------------------------------- +// Form Screens +// --------------------------------------------------------------------------- + +export interface FormScreenField { + id: string; + uid: string; + name: string; + type: string; + data_type: string; + mandatory: boolean; + value?: any; + properties?: { + options?: Array<{ label: string; value: string }>; + country_code?: string; + }; +} + +export interface FormScreenResponse { + id: number; + activity_uid: string; + activity_name: string; + device_type: string; + fields: FormScreenField[]; + grid_config: Array<{ i: string; x: number; y: number; w: number; h: number }>; + layout: any[]; +} + +export function getFormScreen( + activityId: string, + instanceId?: string, + deviceType = "desktop", +): Promise { + const numericInstanceId = instanceId ? Number(instanceId) : undefined; + return request("POST", `/app/${APP_ID}/view/form-screens`, { + activity_id: activityId, + device_type: deviceType, + ...(numericInstanceId && !Number.isNaN(numericInstanceId) + ? { instance_id: numericInstanceId } + : {}), + }); +} + +// --------------------------------------------------------------------------- +// Workflow Actions +// --------------------------------------------------------------------------- + +export interface WorkflowResponse { + success: boolean; + status_code?: number; + message?: string; + data?: Record; + instance_id?: string; +} + +// Core-service expects the workflow UUID as `workflow_uuid` — the numeric +// `workflow_id` field was removed when the clone-portable identifier rolled out. +export function startWorkflow( + workflowUuid: string, + activityId: string, + data?: Record, +): Promise { + return request("POST", `/app/${APP_ID}/start`, { + workflow_uuid: workflowUuid, + activity_id: activityId, + data, + }); +} + +export function performActivity( + workflowUuid: string, + instanceId: string, + activityId: string, + data?: Record, +): Promise { + const numericInstanceId = Number(instanceId); + return request("POST", `/app/${APP_ID}/activity`, { + workflow_uuid: workflowUuid, + instance_id: Number.isNaN(numericInstanceId) ? instanceId : numericInstanceId, + activity_id: activityId, + data, + }); +} + +export function submitForm( + workflowUuid: string, + activityId: string, + formData: Record, + instanceId?: string, + deviceType = "desktop", +): Promise { + const numericInstanceId = instanceId ? Number(instanceId) : undefined; + return request("POST", `/app/${APP_ID}/form/submit`, { + workflow_uuid: workflowUuid, + activity_id: activityId, + device_type: deviceType, + form_data: formData, + ...(numericInstanceId && !Number.isNaN(numericInstanceId) + ? { instance_id: numericInstanceId } + : {}), + }); +} + +// --------------------------------------------------------------------------- +// Instance +// --------------------------------------------------------------------------- + +export interface InstanceResponse { + instance_id: string; + workflow_id: string; + current_state_id: string; + current_state_name: string; + data: Record; + created_at: string; + updated_at: string; +} + +export function getInstance(workflowUuid: string, instanceId: string): Promise { + return request("POST", `/app/${APP_ID}/instance`, { + workflow_uuid: workflowUuid, + instance_id: Number(instanceId), + }); +} + +// --------------------------------------------------------------------------- +// Audit +// --------------------------------------------------------------------------- + +export interface AuditEntry { + id: number; + user_id: string; + user_roles: string[]; + activity_id: string; + data: Record; + execution_state: string; + created_at: string; + // Optional human-readable summary line. Populated by useInstanceMeta when + // the audit is synthesised from instance.data._activities. + context?: string; +} + +export function getAuditLog(instanceId: string): Promise { + return request("GET", `/app/${APP_ID}/view/audit?instance_id=${encodeURIComponent(instanceId)}`); +} + +// --------------------------------------------------------------------------- +// RDBMS lookup records — used by the demo calendar to pull rows from the +// `mahindra_demo` schema via the lookup-field config on the INIT activity. +// --------------------------------------------------------------------------- + +export interface RdbmsLookupResponse { + records: Record[]; + total: number; + limit: number; + offset: number; +} + +export interface RdbmsLookupQuery { + workflowId: number; + activityId: string; + fieldId: string; + limit?: number; + offset?: number; + search?: string; +} + +export function fetchRdbmsLookupRecords(templateUuid: string, q: RdbmsLookupQuery): Promise { + return request("POST", `/app/${APP_ID}/rdbms-templates/${encodeURIComponent(templateUuid)}/records`, { + workflow_id: q.workflowId, + activity_id: q.activityId, + field_id: q.fieldId, + limit: q.limit ?? 1000, + offset: q.offset ?? 0, + search: q.search ?? "", + }); +} diff --git a/src/components/AppShell.tsx b/src/components/AppShell.tsx new file mode 100644 index 0000000..6035456 --- /dev/null +++ b/src/components/AppShell.tsx @@ -0,0 +1,302 @@ +import { useEffect, useState, useCallback } from "react"; +import { useNavigate, useParams } from "react-router-dom"; +import { Loader2, CheckCircle2, XCircle, PauseCircle, MessageSquare, Clock } from "lucide-react"; +import DynamicHeader from "./DynamicHeader"; +import DashboardStats from "./DashboardStats"; +import ScreenRenderer from "./ScreenRenderer"; +import { TableSkeleton } from "./Skeleton"; +import DetailViewPanel from "./DetailViewPanel"; +import FormModal from "./FormModal"; +import { getHeaderConfig, getScreen, getAuditLog, getInstance, type LayoutElement, type NavItem, type AuditEntry } from "../api/viewService"; +import { WORKFLOW_ID, ACTIVITY_IDS, STATE_IDS, SCREEN_UUIDS, RDBMS_RV_SCREEN_UUID, RDBMS_DV_SCREEN_UUID } from "../config"; +import RecordViewTable from "./RecordViewTable"; + +// Keys + values are UUIDs (source_uuid from tbl_appconfig_rv_screens / dv_screens / screens). +const RDBMS_SCREENS: Record = { + [RDBMS_RV_SCREEN_UUID]: RDBMS_RV_SCREEN_UUID, // Purchase Orders (Vendor Data) rv_screen +}; + +const RDBMS_SCREEN_LABELS: Record = { + [RDBMS_RV_SCREEN_UUID]: "Purchase Orders", +}; + +// RDBMS list screen → DV screen (both are dv/rv screen source_uuids). +const RDBMS_DETAIL_SCREENS: Record = { + [RDBMS_RV_SCREEN_UUID]: RDBMS_DV_SCREEN_UUID, +}; + +// List screen → detail screen (tbl_appconfig_screens source_uuid). +const SCREEN_TO_DETAIL_SCREEN: Record = { + [SCREEN_UUIDS.MY_INVOICES]: SCREEN_UUIDS.INVOICE_DETAIL, + [SCREEN_UUIDS.PENDING_CLARIFICATIONS]: SCREEN_UUIDS.CLARIFICATION_DETAIL, + [SCREEN_UUIDS.FINANCE_REVIEW]: SCREEN_UUIDS.FINANCE_REVIEW_DETAIL, + [SCREEN_UUIDS.ALL_INVOICES]: SCREEN_UUIDS.INVOICE_DETAIL, +}; + +const ACTIVITY_META: Record = { + [ACTIVITY_IDS.PROVIDE_CLARIFICATION]: { label: "Provide Clarification", icon: , style: "primary" }, + [ACTIVITY_IDS.APPROVE_PAYMENT]: { label: "Approve", icon: , style: "primary" }, + [ACTIVITY_IDS.REJECT_PAYMENT]: { label: "Reject", icon: , style: "danger" }, + [ACTIVITY_IDS.HOLD_PAYMENT]: { label: "Hold", icon: , style: "ghost" }, +}; + +const BTN_STYLES: Record = { + primary: "text-white shadow-lg shadow-violet-500/25 hover:shadow-violet-500/40 hover:scale-[1.02]", + danger: "text-red-600 dark:text-red-400 bg-white dark:bg-zinc-900 border border-red-200 dark:border-red-800 hover:bg-red-50 dark:hover:bg-red-950/30", + ghost: "text-slate-600 dark:text-zinc-300 bg-white dark:bg-zinc-900 border border-slate-200 dark:border-zinc-700 hover:bg-slate-50 dark:hover:bg-zinc-800", +}; + +export default function AppShell() { + const navigate = useNavigate(); + const params = useParams(); + const screenIdParam = params.screenId ?? null; + const instanceIdParam = params.instanceId; + + const [activeScreenId, setActiveScreenId] = useState(screenIdParam); + const [layout, setLayout] = useState([]); + const [loading, setLoading] = useState(true); + const [ready, setReady] = useState(false); + + const [detailInstanceId, setDetailInstanceId] = useState(instanceIdParam || null); + const [detailViewId, setDetailViewId] = useState(null); + const [detailScreenLayout, setDetailScreenLayout] = useState(null); + + const [refreshKey, setRefreshKey] = useState(0); + const [formModal, setFormModal] = useState<{ activityId: string; instanceId: string; title: string } | null>(null); + const [instanceState, setInstanceState] = useState(null); + const [audit, setAudit] = useState([]); + const [sidebarOpen, setSidebarOpen] = useState(true); + const [navItems, setNavItems] = useState([]); + + // Init + useEffect(() => { + if (!screenIdParam && !instanceIdParam) { + getHeaderConfig("desktop").then((cfg) => { + const items = cfg.components?.nav?.items ?? []; + setNavItems(items); + if (items.length > 0) handleNavigate(items[0].screen_uuid); + }).catch(console.error).finally(() => setReady(true)); + } else { + setReady(true); + if (instanceIdParam && screenIdParam) { + setDetailInstanceId(instanceIdParam); + setDetailViewId(SCREEN_TO_DETAIL_SCREEN[screenIdParam] ?? RDBMS_DETAIL_SCREENS[screenIdParam] ?? SCREEN_UUIDS.INVOICE_DETAIL); + } + } + }, []); + + // Sync detail state with URL params on browser back/forward + useEffect(() => { + if (!params.instanceId && detailInstanceId) { + setDetailInstanceId(null); + setDetailViewId(null); + setDetailScreenLayout(null); + setInstanceState(null); + setAudit([]); + } else if (params.instanceId && params.instanceId !== detailInstanceId) { + setDetailInstanceId(params.instanceId); + const sid = params.screenId ?? activeScreenId; + if (sid) setDetailViewId(SCREEN_TO_DETAIL_SCREEN[sid] ?? RDBMS_DETAIL_SCREENS[sid] ?? SCREEN_UUIDS.INVOICE_DETAIL); + } + }, [params.instanceId]); + + // Load screen layout (skip for RDBMS screens — rendered directly) + useEffect(() => { + if (!activeScreenId || detailInstanceId) return; + if (RDBMS_SCREENS[activeScreenId]) { setLoading(false); return; } + setLoading(true); + getScreen(activeScreenId) + .then((s) => setLayout(s.layout ?? [])) + .catch(console.error) + .finally(() => setLoading(false)); + }, [activeScreenId, detailInstanceId]); + + // Load detail screen + useEffect(() => { + if (!detailViewId) return; + getScreen(detailViewId) + .then((s) => setDetailScreenLayout(s.layout ?? [])) + .catch(() => setDetailScreenLayout(null)); + }, [detailViewId]); + + // Load instance state + audit + useEffect(() => { + if (!detailInstanceId) return; + getInstance(WORKFLOW_ID, detailInstanceId) + .then((inst) => setInstanceState(inst.current_state_id)) + .catch(() => {}); + getAuditLog(detailInstanceId).then(setAudit).catch(() => setAudit([])); + }, [detailInstanceId]); + + const handleNavigate = useCallback((id: string) => { + setActiveScreenId(id); setDetailInstanceId(null); setDetailViewId(null); + setDetailScreenLayout(null); setInstanceState(null); setAudit([]); + if (RDBMS_SCREENS[id]) setLayout([]); + navigate(`/screen/${id}`); + }, [navigate]); + + const handleRowClick = useCallback((instanceId: string) => { + const dvScreenId = activeScreenId ? (SCREEN_TO_DETAIL_SCREEN[activeScreenId] ?? SCREEN_UUIDS.INVOICE_DETAIL) : SCREEN_UUIDS.INVOICE_DETAIL; + setDetailInstanceId(instanceId); + setDetailViewId(dvScreenId); + navigate(`/screen/${activeScreenId}/detail/${instanceId}`); + }, [activeScreenId, navigate]); + + const handleBack = () => { + setDetailInstanceId(null); setDetailViewId(null); setDetailScreenLayout(null); + setInstanceState(null); setAudit([]); + navigate(`/screen/${activeScreenId}`); + }; + + const handleFormSuccess = () => { + setFormModal(null); + if (detailInstanceId) { + const v = detailViewId; setDetailViewId(null); setTimeout(() => setDetailViewId(v), 50); + getAuditLog(detailInstanceId).then(setAudit).catch(() => {}); + } + }; + + const actions = (() => { + if (!instanceState) return []; + if (instanceState === STATE_IDS.AWAITING_CLARIFICATION) return [ACTIVITY_IDS.PROVIDE_CLARIFICATION]; + if (instanceState === STATE_IDS.FINANCE_REVIEW) return [ACTIVITY_IDS.APPROVE_PAYMENT, ACTIVITY_IDS.REJECT_PAYMENT, ACTIVITY_IDS.HOLD_PAYMENT]; + return []; + })(); + + if (!ready) return ( +
+
+ + Loading… +
+
+ ); + + return ( +
+ + +
+
+ {detailInstanceId && detailViewId ? ( +
+
+ {/* Breadcrumb */} + + {actions.length > 0 && ( +
+ {actions.map((id) => { + const m = ACTIVITY_META[id]; + if (!m) return null; + return ( + + ); + })} +
+ )} +
+ + {detailScreenLayout ? : } + + {audit.length > 0 && ( +
+
+
+ +
+

Activity Timeline

+ {audit.length} events +
+
+
+
+
+ {audit.map((e, i) => { + const isFirst = i === 0; + const isLast = i === audit.length - 1; + return ( +
+
+
+
+ + {fmtAct(e.activity_id)} + + {isLast && ( + + Latest + + )} +
+ + {new Date(e.created_at).toLocaleString("en-IN", { day: "2-digit", month: "short", hour: "2-digit", minute: "2-digit" })} + +
+
+ ); + })} +
+
+
+
+ )} +
+ ) : loading ? ( + <> + ) : activeScreenId && RDBMS_SCREENS[activeScreenId] ? ( + { + setDetailInstanceId(pkValue); + setDetailViewId(RDBMS_DETAIL_SCREENS[activeScreenId]); + navigate(`/screen/${activeScreenId}/detail/${pkValue}`); + } : undefined} + /> + ) : layout.length > 0 ? ( + <> setRefreshKey((k) => k + 1)} /> + ) : ( +
Select a screen from the navigation
+ )} +
+
+ + {formModal && setFormModal(null)} onSuccess={handleFormSuccess} />} +
+ ); +} + +function fmtAct(id: string): string { return id.replace(/^p2p-act-/, "").replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()); } diff --git a/src/components/DashboardStats.tsx b/src/components/DashboardStats.tsx new file mode 100644 index 0000000..b90d1c8 --- /dev/null +++ b/src/components/DashboardStats.tsx @@ -0,0 +1,84 @@ +import { useEffect, useState } from "react"; +import { FileText, AlertCircle, Clock, CheckCircle2 } from "lucide-react"; +import { getRecordView, getRVScreen } from "../api/viewService"; +import { StatsSkeleton } from "./Skeleton"; +import { ALL_INVOICES_RV_SCREEN_UUID, RECORD_VIEW_IDS } from "../config"; + +const ALL_INVOICES_VIEW = ALL_INVOICES_RV_SCREEN_UUID; + +interface Stats { + total: number; + pendingClarification: number; + financeReview: number; + approved: number; +} + +export default function DashboardStats() { + const [stats, setStats] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + async function fetchStats() { + try { + const rvScreen = await getRVScreen(ALL_INVOICES_VIEW); + const id = rvScreen.rv_template_uid; + const rvUid = RECORD_VIEW_IDS.ALL_INVOICES; + + // Step 1: get exact total from pagination + const countRes = await getRecordView(id, rvUid, { page: 1, limit: 1 }); + const total = countRes.pagination?.total_count ?? 0; + + let pendingClarification = 0, financeReview = 0, approved = 0; + + if (total > 0) { + // Step 2: fetch all rows in one call using exact total as limit + const allRes = await getRecordView(id, rvUid, { page: 1, limit: total }); + for (const row of allRes.data ?? []) { + const state = String(row.current_state_name ?? ""); + if (state === "Awaiting Clarification") pendingClarification++; + else if (state === "Finance Review") financeReview++; + else if (state === "Approved") approved++; + } + } + + setStats({ total, pendingClarification, financeReview, approved }); + } catch { + setStats({ total: 0, pendingClarification: 0, financeReview: 0, approved: 0 }); + } finally { + setLoading(false); + } + } + fetchStats(); + }, []); + + if (loading) return ; + if (!stats) return null; + + const cards = [ + { label: "Total Invoices", value: stats.total, icon: FileText, color: "text-slate-500 dark:text-zinc-400", bg: "bg-slate-100 dark:bg-zinc-800" }, + { label: "Pending Clarification", value: stats.pendingClarification, icon: AlertCircle, color: "text-amber-600 dark:text-amber-400", bg: "bg-amber-50 dark:bg-amber-950/40" }, + { label: "Finance Review", value: stats.financeReview, icon: Clock, color: "text-indigo-600 dark:text-indigo-400", bg: "bg-indigo-50 dark:bg-indigo-950/40" }, + { label: "Approved", value: stats.approved, icon: CheckCircle2, color: "text-emerald-600 dark:text-emerald-400", bg: "bg-emerald-50 dark:bg-emerald-950/40" }, + ]; + + return ( +
+ {cards.map((card) => { + const Icon = card.icon; + return ( +
+
+ +
+
+
+ {card.value} +
+
{card.label}
+
+
+ ); + })} +
+ ); +} diff --git a/src/components/DetailViewPanel.tsx b/src/components/DetailViewPanel.tsx new file mode 100644 index 0000000..a30252a --- /dev/null +++ b/src/components/DetailViewPanel.tsx @@ -0,0 +1,363 @@ +import { useEffect, useState, useRef } from "react"; +import { Hash, Calendar, Sparkles, TrendingUp, MessageSquare, ChevronDown, ChevronUp } from "lucide-react"; +import { getDVScreen, getDetailView } from "../api/viewService"; +import { DetailSkeleton } from "./Skeleton"; + +interface Field { field_key: string; output_label: string; data_type: string } +interface Props { viewId: number | string; instanceId: string } + +type GroupKey = "hero" | "vendor" | "financial" | "dates" | "ai" | "general"; + +// --------------------------------------------------------------------------- +// Classification +// --------------------------------------------------------------------------- + +function classify(key: string): GroupKey { + const k = key.toLowerCase(); + if (["invoice_number", "invoice_no", "inv_number", "po_number", "po_no", "order_number"].includes(k)) return "hero"; + if (k.startsWith("ai_") || k.includes("recommendation") || k.includes("confidence") || + k.includes("clarification") || k.includes("analysis") || k.includes("risk") || + k.includes("anomal") || k.includes("match_summary") || k.includes("reasoning") || + k.includes("reviewer") || k.includes("rejection") || k.includes("hold_reason") || + k.includes("response_text") || k.includes("response_notes") || + k.includes("confirmed_quantity") || k === "target_department" || + k.includes("recommended_amount") || k.includes("approved_amount")) return "ai"; + if (k.startsWith("vendor") || k.startsWith("supplier") || k === "gstin" || k === "pan") return "vendor"; + if (["total_amount","tax_amount","net_amount","gross_amount","subtotal","discount", + "tds","cgst","sgst","igst","cess","line_total","line_amount"].includes(k) || + ["price","cost","payment"].some(x => k.includes(x))) return "financial"; + if (k.includes("date") || k.includes("due") || k.includes("delivery") || k.includes("expected") || + k === "period" || k === "financial_year") return "dates"; + return "general"; +} + +// --------------------------------------------------------------------------- +// Status +// --------------------------------------------------------------------------- + +const STATUS: Record = { + "Invoice Submitted": { pill: "text-sky-700 bg-sky-50 ring-sky-200 dark:text-sky-300 dark:bg-sky-950/50 dark:ring-sky-800/60", dot: "bg-sky-500", bar: "bg-sky-500" }, + "AI Analysis": { pill: "text-violet-700 bg-violet-50 ring-violet-200 dark:text-violet-300 dark:bg-violet-950/50 dark:ring-violet-800/60", dot: "bg-violet-500", bar: "bg-violet-500", pulse: true }, + "Awaiting Clarification": { pill: "text-amber-700 bg-amber-50 ring-amber-200 dark:text-amber-300 dark:bg-amber-950/50 dark:ring-amber-800/60", dot: "bg-amber-500", bar: "bg-amber-400" }, + "Finance Review": { pill: "text-indigo-700 bg-indigo-50 ring-indigo-200 dark:text-indigo-300 dark:bg-indigo-950/50 dark:ring-indigo-800/60", dot: "bg-indigo-500", bar: "bg-indigo-500" }, + "Approved": { pill: "text-emerald-700 bg-emerald-50 ring-emerald-200 dark:text-emerald-300 dark:bg-emerald-950/50 dark:ring-emerald-800/60", dot: "bg-emerald-500", bar: "bg-emerald-500" }, + "Rejected": { pill: "text-red-700 bg-red-50 ring-red-200 dark:text-red-300 dark:bg-red-950/50 dark:ring-red-800/60", dot: "bg-red-500", bar: "bg-red-500" }, + "On Hold": { pill: "text-slate-600 bg-slate-100 ring-slate-200 dark:text-zinc-400 dark:bg-zinc-800 dark:ring-zinc-700", dot: "bg-slate-400", bar: "bg-slate-400" }, + // PO statuses + "Pending": { pill: "text-amber-700 bg-amber-50 ring-amber-200 dark:text-amber-300 dark:bg-amber-950/50 dark:ring-amber-800/60", dot: "bg-amber-500", bar: "bg-amber-400" }, + "Delivered": { pill: "text-sky-700 bg-sky-50 ring-sky-200 dark:text-sky-300 dark:bg-sky-950/50 dark:ring-sky-800/60", dot: "bg-sky-500", bar: "bg-sky-500" }, + "Cancelled": { pill: "text-red-700 bg-red-50 ring-red-200 dark:text-red-300 dark:bg-red-950/50 dark:ring-red-800/60", dot: "bg-red-500", bar: "bg-red-500" }, +}; +const DS: { pill: string; dot: string; bar: string; pulse?: boolean } = { pill: "text-slate-600 bg-slate-100 ring-slate-200 dark:text-zinc-400 dark:bg-zinc-800 dark:ring-zinc-700", dot: "bg-slate-400", bar: "bg-slate-300" }; + +// Fields that are raw JSON — don't render +const SKIP_KEYS = new Set(["analysis_so_far"]); + +// --------------------------------------------------------------------------- +// Main +// --------------------------------------------------------------------------- + +export default function DetailViewPanel({ viewId, instanceId }: Props) { + const [data, setData] = useState | null>(null); + const [fields, setFields] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + if (!instanceId) return; + setLoading(true); setError(null); + getDVScreen(viewId) + .then(dv => getDetailView(dv.dv_template_uid, instanceId)) + .catch(() => getDetailView(viewId, instanceId)) + .then(res => { + setFields(res.config?.fields?.filter((f: any) => f.field_key !== "") ?? []); + setData(res.data ?? {}); + }) + .catch((e: any) => setError(e.message)) + .finally(() => setLoading(false)); + }, [viewId, instanceId]); + + if (loading) return ; + if (error) return

{error}

; + if (!data || !fields.length) return null; + + const sys = new Set(["instance_id", "current_state_name", "created_at", "updated_at", "po_status"]); + const groups: Record = { hero: [], vendor: [], financial: [], dates: [], ai: [], general: [] }; + + for (const f of fields) { + if (sys.has(f.field_key) || SKIP_KEYS.has(f.field_key)) continue; + const v = data[f.field_key]; + const g = classify(f.field_key); + if (g !== "hero" && (v == null || v === "")) continue; + groups[g].push(f); + } + + const heroField = groups.hero[0]; + const heroValue = heroField ? String(data[heroField.field_key] ?? "") : ""; + const stateName = String(data.current_state_name ?? data.po_status ?? ""); + const sc = STATUS[stateName] ?? DS; + + // Primary amount shown large in header, removed from financials grid + const primaryF = groups.financial.find(f => + ["total_amount","amount","net_amount","gross_amount"].includes(f.field_key.toLowerCase()) + ); + const primaryAmt = primaryF ? Number(data[primaryF.field_key] ?? 0) : null; + const financials = groups.financial.filter(f => f !== primaryF); + + // Vendor name for subtitle + const vendorNameF = groups.vendor.find(f => f.field_key === "vendor_name"); + const vendorName = vendorNameF ? String(data.vendor_name ?? "") : ""; + + // Left columns: dates + general + vendor (compact metadata) + const isPoView = !!data.po_status || !!data.po_number; + const leftGroups = [ + { label: isPoView ? "Order Details" : "Invoice Details", fields: [...groups.dates, ...groups.general] }, + { label: "Vendor", fields: groups.vendor }, + ].filter(g => g.fields.length > 0); + + // AI fields: short = inline grid (includes confidence bar), long = full-width text blocks + const isScore = (f: Field) => f.field_key.toLowerCase().includes("confidence") || f.field_key.toLowerCase().includes("score"); + const isLongText = (f: Field) => { const v = data[f.field_key]; return typeof v === "string" && v.length > 55; }; + + const aiShort = groups.ai.filter(f => isScore(f) || !isLongText(f)); + const aiLong = groups.ai.filter(f => !isScore(f) && isLongText(f)); + + return ( +
+ + {/* Status bar */} +
+ + {/* ── Header ──────────────────────────────────────────────────── */} +
+ + {/* Row 1: invoice number + status + amount */} +
+
+ {heroValue && ( +

+ {heroValue} +

+ )} + {stateName && ( + + + {stateName} + + )} +
+ + {primaryAmt !== null && primaryAmt > 0 && ( +
+

Total Amount

+

+ {fmtCurrency(primaryAmt)} +

+
+ )} +
+ + {/* Row 2: vendor + meta chips */} +
+ {vendorName && ( + {vendorName} + )} + {vendorName && (data.created_at || data.instance_id) && ( + · + )} + {data.created_at && ( + + {fmtDate(String(data.created_at))} + + )} + {data.instance_id && ( + + {String(data.instance_id).slice(0, 16)} + + )} +
+
+ + {/* ── Two-column metadata ──────────────────────────────────────── */} + {(leftGroups.length > 0 || financials.length > 0) && ( +
+ + {/* Left — invoice details + vendor */} +
+ {leftGroups.map(({ label, fields: fs }) => ( +
+

{label}

+
+ {fs.map(f => ( +
+
{fmtLabel(f.output_label)}
+
+ {fmtVal(data[f.field_key], f.data_type, f.field_key)} +
+
+ ))} +
+
+ ))} +
+ + {/* Right — financials */} +
+

Financials

+ {financials.length > 0 ? ( +
+ {financials + .filter(f => !f.field_key.toLowerCase().includes("total") && !f.field_key.toLowerCase().includes("net")) + .map(f => { + const n = Number(data[f.field_key] ?? 0); + return ( +
+ {fmtLabel(f.output_label)} + {n ? fmtCurrency(n) : "—"} +
+ ); + })} + {financials + .filter(f => f.field_key.toLowerCase().includes("total") || f.field_key.toLowerCase().includes("net")) + .map(f => { + const n = Number(data[f.field_key] ?? 0); + return ( +
+ + {fmtLabel(f.output_label)} + + {n ? fmtCurrency(n) : "—"} +
+ ); + })} +
+ ) : ( +

+ )} +
+
+ )} + + {/* ── AI Analysis — full width ─────────────────────────────────── */} + {groups.ai.length > 0 && ( +
+

+ AI Analysis +

+ + {/* Short fields + confidence bars — inline grid */} + {aiShort.length > 0 && ( +
+ {aiShort.map(f => { + const val = data[f.field_key]; + const score = isScore(f); + const num = score ? Number(val) : null; + const pct = num !== null ? Math.min(num > 1 ? num : num * 100, 100) : 0; + const barCls = pct >= 70 ? "bg-emerald-500" : pct >= 40 ? "bg-amber-500" : "bg-red-500"; + const pctCls = pct >= 70 ? "text-emerald-600 dark:text-emerald-400" : pct >= 40 ? "text-amber-600 dark:text-amber-400" : "text-red-500"; + return ( +
+
{fmtLabel(f.output_label)}
+ {score && num !== null ? ( +
+
+
+
+ {pct.toFixed(0)}% +
+ ) : ( +
+ {fmtVal(val, f.data_type, f.field_key)} +
+ )} +
+ ); + })} +
+ )} + + {/* Long text fields — full-width clamped paragraphs */} + {aiLong.length > 0 && ( +
+ {aiLong.map(f => { + const val = data[f.field_key]; + const isClarif = f.field_key.includes("clarification") || f.field_key.includes("response"); + return ( +
+
+ {isClarif && } + {fmtLabel(f.output_label)} +
+ +
+ ); + })} +
+ )} +
+ )} +
+ ); +} + +// --------------------------------------------------------------------------- +// ClampedText — show 3 lines, expand on demand +// --------------------------------------------------------------------------- + +function ClampedText({ text }: { text: string }) { + const [expanded, setExpanded] = useState(false); + const [clamped, setClamped] = useState(false); + const ref = useRef(null); + + useEffect(() => { + const el = ref.current; + if (el) setClamped(el.scrollHeight > el.clientHeight + 2); + }, [text]); + + return ( +
+

+ {text} +

+ {(clamped || expanded) && ( + + )} +
+ ); +} + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +function fmtLabel(label: string): string { + return label.replace(/_/g, " ").replace(/\b\w/g, c => c.toUpperCase()); +} + +function fmtVal(val: unknown, type: string, key: string): string { + if (val == null || val === "") return "—"; + if (type === "number") { + const n = Number(val); + if (["amount","tax","price","cost"].some(x => key.toLowerCase().includes(x))) return fmtCurrency(n); + return n.toLocaleString("en-IN"); + } + if (type === "datetime" || type === "date") return fmtDate(String(val)); + return String(val); +} + +function fmtCurrency(n: number): string { + return n.toLocaleString("en-IN", { style: "currency", currency: "INR", maximumFractionDigits: 0 }); +} + +function fmtDate(val: string): string { + try { return new Date(val).toLocaleDateString("en-IN", { day: "2-digit", month: "short", year: "numeric" }); } + catch { return val; } +} diff --git a/src/components/DynamicHeader.tsx b/src/components/DynamicHeader.tsx new file mode 100644 index 0000000..dbbcfca --- /dev/null +++ b/src/components/DynamicHeader.tsx @@ -0,0 +1,251 @@ +import { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { + LogOut, FileText, HelpCircle, Landmark, List, + Settings, PanelLeftClose, PanelLeftOpen, Sun, Moon, ShoppingCart, +} from "lucide-react"; +import { getHeaderConfig, type HeaderConfig, type NavItem } from "../api/viewService"; +import { useAuthContext } from "../hooks/AuthContext"; +import { useTheme } from "../hooks/ThemeContext"; +import { RDBMS_RV_SCREEN_UUID } from "../config"; + +const ICON_MAP: Record = { + receipt_long: , + help_outline: , + account_balance: , + list_alt: , + inventory_2: , + question_mark: , + list: , +}; + +const EXTRA_NAV_ITEMS = [ + { id: "vendor-data", screen_uuid: RDBMS_RV_SCREEN_UUID, label: "Purchase Orders", icon: }, +]; + +interface Props { + activeScreenId: string | null; + onNavigate: (screenUuid: string) => void; + onSidebarChange?: (open: boolean) => void; +} + +export default function DynamicHeader({ activeScreenId, onNavigate, onSidebarChange }: Props) { + const { user, logout } = useAuthContext(); + const { theme, toggleTheme } = useTheme(); + const navigate = useNavigate(); + const [config, setConfig] = useState(null); + const [profileOpen, setProfileOpen] = useState(false); + const [sidebarOpen, setSidebarOpen] = useState(true); + + useEffect(() => { + getHeaderConfig("desktop").then(setConfig).catch(console.error); + }, []); + + const navItems = config?.components?.nav?.items ?? []; + const handleLogout = () => { logout(); navigate("/login"); }; + + const initials = (user?.name || "U") + .split(" ").map((n) => n[0]).join("").slice(0, 2).toUpperCase(); + const roleName = user?.roles?.[0] + ?.replace(/^p2p_/, "").replace(/_/g, " ") ?? ""; + + const toggleSidebar = () => { + const next = !sidebarOpen; + setSidebarOpen(next); + onSidebarChange?.(next); + }; + + return ( + <> + {/* ── Top bar ─────────────────────────────────────────────────────── */} +
+ {/* Left */} +
+ + + {/* Logo — unchanged from original */} + Zino +
+ + {/* Right */} +
+ {/* Theme toggle */} + + + {/* Avatar */} +
+ + + {profileOpen && ( + <> +
setProfileOpen(false)} /> +
+
+
+
+ {initials} +
+
+
{user?.name}
+
{user?.email}
+
+
+ {roleName && ( +
+ + {roleName} + +
+ )} +
+
+ +
+ +
+
+ + )} +
+
+
+ + {/* ── Sidebar ─────────────────────────────────────────────────────── */} + + + ); +} diff --git a/src/components/FormModal.tsx b/src/components/FormModal.tsx new file mode 100644 index 0000000..cccd07d --- /dev/null +++ b/src/components/FormModal.tsx @@ -0,0 +1,257 @@ +import { useEffect, useState, useRef } from "react"; +import { X, ArrowRight, AlertCircle, CheckCircle2, ChevronDown } from "lucide-react"; +import { getFormScreen, startWorkflow, performActivity } from "../api/viewService"; +import { WORKFLOW_ID } from "../config"; +import { Skeleton } from "./Skeleton"; + +interface FormField { id: string; uid: string; name: string; type: string; data_type: string; mandatory: boolean; value?: any; properties?: { options?: Array<{ label: string; value: string }>; country_code?: string }; } +interface GridItem { i: string; x: number; y: number; w: number; h: number; } + +interface Props { + activityId: string; + instanceId?: string; + title?: string; + onClose: () => void; + onSuccess: () => void; +} + +export default function FormModal({ activityId, instanceId, title, onClose, onSuccess }: Props) { + const [fields, setFields] = useState([]); + const [gridConfig, setGridConfig] = useState([]); + const [formTitle, setFormTitle] = useState(title || ""); + const [formData, setFormData] = useState>({}); + const [loading, setLoading] = useState(true); + const [submitting, setSubmitting] = useState(false); + const [error, setError] = useState(null); + const [touched, setTouched] = useState>(new Set()); + const [success, setSuccess] = useState(false); + const [visible, setVisible] = useState(false); + const modalRef = useRef(null); + + // Entrance animation + useEffect(() => { requestAnimationFrame(() => setVisible(true)); }, []); + + useEffect(() => { + getFormScreen(activityId, instanceId) + .then((res: any) => { + const f: FormField[] = res.fields ?? res.form_json?.fields ?? []; + setFields(f); + setGridConfig(res.grid_config ?? []); + setFormTitle(res.activity_name || title || "Form"); + const pre: Record = {}; + f.forEach((field) => { if (field.value != null) pre[field.id] = String(field.value); }); + setFormData(pre); + }) + .catch((err: any) => setError(err.message)) + .finally(() => setLoading(false)); + }, [activityId, instanceId, title]); + + const animateClose = (callback: () => void) => { + setVisible(false); + setTimeout(callback, 200); + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setTouched(new Set(fields.map((f) => f.id))); + + const missing = fields.filter((f) => f.mandatory && !formData[f.id]?.trim()); + if (missing.length > 0) { + setError(`Please fill in: ${missing.map((f) => f.name).join(", ")}`); + return; + } + + setSubmitting(true); setError(null); + try { + const data: Record = {}; + for (const f of fields) { const v = formData[f.id] ?? ""; data[f.id] = f.data_type === "number" ? (v ? Number(v) : 0) : v; } + instanceId ? await performActivity(WORKFLOW_ID, instanceId, activityId, data) : await startWorkflow(WORKFLOW_ID, activityId, data); + setSuccess(true); + setTimeout(() => animateClose(onSuccess), 800); + } catch (err: any) { setError(err.message || "Failed"); } + finally { setSubmitting(false); } + }; + + const sorted = [...fields].sort((a, b) => { + const ga = gridConfig.find((g) => g.i === a.uid), gb = gridConfig.find((g) => g.i === b.uid); + if (!ga || !gb) return 0; + return ga.y !== gb.y ? ga.y - gb.y : ga.x - gb.x; + }); + + const rows: FormField[][] = []; let cy = -1; + for (const f of sorted) { const g = gridConfig.find((gi) => gi.i === f.uid); const y = g?.y ?? rows.length; if (y !== cy) { rows.push([]); cy = y; } rows[rows.length - 1].push(f); } + + const isMissing = (f: FormField) => f.mandatory && touched.has(f.id) && !formData[f.id]?.trim(); + + return ( +
animateClose(onClose)}> + {/* Backdrop */} +
+ + {/* Modal */} +
e.stopPropagation()} + > + {/* ── Success overlay ──────────────────────────────────────────── */} + {success && ( +
+
+ +
+
Submitted successfully
+
+ )} + + {/* ── Header ───────────────────────────────────────────────────── */} +
+
+

{formTitle}

+

+ {instanceId ? "Update the details below" : "Fill in the details to submit"} +

+
+ +
+ + {/* ── Body ─────────────────────────────────────────────────────── */} +
+ {loading ? ( +
+ {[0, 1, 2, 3].map((r) => ( +
+
+
+
+ ))} +
+ ) : ( +
+ {rows.map((row, ri) => ( +
1 ? "grid-cols-2" : "grid-cols-1"}`}> + {row.map((f) => ( +
+ + {renderInput(f, formData[f.id] ?? "", (v) => { + setFormData((p) => ({ ...p, [f.id]: v })); + setTouched((t) => new Set(t).add(f.id)); + if (error) setError(null); + }, isMissing(f))} + {isMissing(f) && ( +

+ Required +

+ )} +
+ ))} +
+ ))} +
+ )} + + {error && ( +
+ + {error} +
+ )} +
+ + {/* ── Footer ───────────────────────────────────────────────────── */} + {!loading && ( +
+
+ * Required +
+
+ + +
+
+ )} +
+
+ ); +} + +// --------------------------------------------------------------------------- +// Input renderer +// --------------------------------------------------------------------------- + +function renderInput(f: FormField, value: string, onChange: (v: string) => void, hasError: boolean) { + const base = `w-full h-10 border rounded-xl px-3.5 text-[13px] bg-slate-50/50 dark:bg-zinc-800/70 focus:bg-white dark:focus:bg-zinc-800 text-slate-800 dark:text-zinc-100 focus:outline-none focus:ring-2 transition placeholder:text-slate-400 dark:placeholder:text-zinc-600 ${ + hasError + ? "border-red-300 dark:border-red-700 focus:ring-red-500/20 focus:border-red-400" + : "border-slate-200 dark:border-zinc-700 focus:ring-violet-500/20 focus:border-violet-400 dark:focus:border-violet-500" + }`; + + // Select / radio with options + const opts = f.properties?.options; + if (opts && opts.length > 0) { + return ( +
+ + +
+ ); + } + + switch (f.data_type) { + case "longtext": + return ( +