From 391b355e8d3b556fad510e88b2c7fc048549aeab Mon Sep 17 00:00:00 2001 From: randy-ar Date: Thu, 20 Nov 2025 18:15:42 +0700 Subject: [PATCH] feat(FE-181-179-220-271): adding SO export PDF and adjusting delivery form --- package-lock.json | 519 +++++++++++++++++- package.json | 3 +- .../edit => add/delivery-orders}/layout.tsx | 0 .../delivery => add/delivery-orders}/page.tsx | 10 +- .../add => add/sales-orders}/page.tsx | 4 +- .../delivery-orders/edit}/layout.tsx | 0 .../detail/delivery-orders/edit/page.tsx | 62 +++ src/app/marketing/detail/layout.tsx | 11 + .../{sales-orders => }/detail/page.tsx | 10 +- .../detail/sales-orders/edit/layout.tsx | 11 + .../sales-orders}/edit/page.tsx | 6 +- src/app/marketing/page.tsx | 10 + src/app/marketing/sales-orders/page.tsx | 10 - .../pages/marketing/MarketingTable.tsx | 59 +- .../marketing/detail/MarketingDetail.tsx | 23 +- .../marketing/form/MarketingForm.schema.ts | 17 +- .../pages/marketing/form/MarketingForm.tsx | 277 ++++++---- .../DeliverOrderProduct.schema.ts | 9 +- .../delivery-order/DeliverOrderProduct.tsx | 77 +-- .../sales-order/SalesOrderProduct.schema.ts | 2 +- .../sales-order/SalesOrderProductForm.tsx | 3 + .../table-view/DeliveryOrderProductTable.tsx | 171 +++--- .../marketing/pdf/DeliveryOrderExport.tsx | 0 .../pages/marketing/pdf/SalesOrderExport.tsx | 227 ++++++++ .../pdf/styles/MarketingPDFStyles.tsx | 212 +++++++ src/config/constant.ts | 2 +- 26 files changed, 1490 insertions(+), 245 deletions(-) rename src/app/marketing/{sales-orders/detail/edit => add/delivery-orders}/layout.tsx (100%) rename src/app/marketing/{sales-orders/detail/edit/delivery => add/delivery-orders}/page.tsx (84%) rename src/app/marketing/{sales-orders/add => add/sales-orders}/page.tsx (52%) rename src/app/marketing/{sales-orders/detail => detail/delivery-orders/edit}/layout.tsx (100%) create mode 100644 src/app/marketing/detail/delivery-orders/edit/page.tsx create mode 100644 src/app/marketing/detail/layout.tsx rename src/app/marketing/{sales-orders => }/detail/page.tsx (82%) create mode 100644 src/app/marketing/detail/sales-orders/edit/layout.tsx rename src/app/marketing/{sales-orders/detail => detail/sales-orders}/edit/page.tsx (89%) create mode 100644 src/app/marketing/page.tsx delete mode 100644 src/app/marketing/sales-orders/page.tsx create mode 100644 src/components/pages/marketing/pdf/DeliveryOrderExport.tsx create mode 100644 src/components/pages/marketing/pdf/SalesOrderExport.tsx create mode 100644 src/components/pages/marketing/pdf/styles/MarketingPDFStyles.tsx diff --git a/package-lock.json b/package-lock.json index f64e3a8f..b5a70787 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "lti-web-client", "version": "0.1.0", "dependencies": { + "@react-pdf/renderer": "^4.3.1", "@tanstack/match-sorter-utils": "^8.19.4", "@tanstack/react-table": "^8.21.3", "axios": "^1.12.2", @@ -1274,6 +1275,180 @@ "node": ">=12.4.0" } }, + "node_modules/@react-pdf/fns": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@react-pdf/fns/-/fns-3.1.2.tgz", + "integrity": "sha512-qTKGUf0iAMGg2+OsUcp9ffKnKi41RukM/zYIWMDJ4hRVYSr89Q7e3wSDW/Koqx3ea3Uy/z3h2y3wPX6Bdfxk6g==", + "license": "MIT" + }, + "node_modules/@react-pdf/font": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@react-pdf/font/-/font-4.0.3.tgz", + "integrity": "sha512-N1qQDZr6phXYQOp033Hvm2nkUkx2LkszjGPbmRavs9VOYzi4sp31MaccMKptL24ii6UhBh/z9yPUhnuNe/qHwA==", + "license": "MIT", + "dependencies": { + "@react-pdf/pdfkit": "^4.0.4", + "@react-pdf/types": "^2.9.1", + "fontkit": "^2.0.2", + "is-url": "^1.2.4" + } + }, + "node_modules/@react-pdf/image": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@react-pdf/image/-/image-3.0.3.tgz", + "integrity": "sha512-lvP5ryzYM3wpbO9bvqLZYwEr5XBDX9jcaRICvtnoRqdJOo7PRrMnmB4MMScyb+Xw10mGeIubZAAomNAG5ONQZQ==", + "license": "MIT", + "dependencies": { + "@react-pdf/png-js": "^3.0.0", + "jay-peg": "^1.1.1" + } + }, + "node_modules/@react-pdf/layout": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@react-pdf/layout/-/layout-4.4.1.tgz", + "integrity": "sha512-GVzdlWoZWldRDzlWj3SttRXmVDxg7YfraAohwy+o9gb9hrbDJaaAV6jV3pc630Evd3K46OAzk8EFu8EgPDuVuA==", + "license": "MIT", + "dependencies": { + "@react-pdf/fns": "3.1.2", + "@react-pdf/image": "^3.0.3", + "@react-pdf/primitives": "^4.1.1", + "@react-pdf/stylesheet": "^6.1.1", + "@react-pdf/textkit": "^6.0.0", + "@react-pdf/types": "^2.9.1", + "emoji-regex-xs": "^1.0.0", + "queue": "^6.0.1", + "yoga-layout": "^3.2.1" + } + }, + "node_modules/@react-pdf/pdfkit": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@react-pdf/pdfkit/-/pdfkit-4.0.4.tgz", + "integrity": "sha512-/nITLggsPlB66bVLnm0X7MNdKQxXelLGZG6zB5acF5cCgkFwmXHnLNyxYOUD4GMOMg1HOPShXDKWrwk2ZeHsvw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/png-js": "^3.0.0", + "browserify-zlib": "^0.2.0", + "crypto-js": "^4.2.0", + "fontkit": "^2.0.2", + "jay-peg": "^1.1.1", + "linebreak": "^1.1.0", + "vite-compatible-readable-stream": "^3.6.1" + } + }, + "node_modules/@react-pdf/png-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@react-pdf/png-js/-/png-js-3.0.0.tgz", + "integrity": "sha512-eSJnEItZ37WPt6Qv5pncQDxLJRK15eaRwPT+gZoujP548CodenOVp49GST8XJvKMFt9YqIBzGBV/j9AgrOQzVA==", + "license": "MIT", + "dependencies": { + "browserify-zlib": "^0.2.0" + } + }, + "node_modules/@react-pdf/primitives": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@react-pdf/primitives/-/primitives-4.1.1.tgz", + "integrity": "sha512-IuhxYls1luJb7NUWy6q5avb1XrNaVj9bTNI40U9qGRuS6n7Hje/8H8Qi99Z9UKFV74bBP3DOf3L1wV2qZVgVrQ==", + "license": "MIT" + }, + "node_modules/@react-pdf/reconciler": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@react-pdf/reconciler/-/reconciler-1.1.4.tgz", + "integrity": "sha512-oTQDiR/t4Z/Guxac88IavpU2UgN7eR0RMI9DRKvKnvPz2DUasGjXfChAdMqDNmJJxxV26mMy9xQOUV2UU5/okg==", + "license": "MIT", + "dependencies": { + "object-assign": "^4.1.1", + "scheduler": "0.25.0-rc-603e6108-20241029" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@react-pdf/reconciler/node_modules/scheduler": { + "version": "0.25.0-rc-603e6108-20241029", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0-rc-603e6108-20241029.tgz", + "integrity": "sha512-pFwF6H1XrSdYYNLfOcGlM28/j8CGLu8IvdrxqhjWULe2bPcKiKW4CV+OWqR/9fT52mywx65l7ysNkjLKBda7eA==", + "license": "MIT" + }, + "node_modules/@react-pdf/render": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@react-pdf/render/-/render-4.3.1.tgz", + "integrity": "sha512-v1WAaAhQShQZGcBxfjkEThGCHVH9CSuitrZ1bIOLvB5iBKM14abYK5D6djKhWCwF6FTzYeT2WRjRMVgze/ND2A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/fns": "3.1.2", + "@react-pdf/primitives": "^4.1.1", + "@react-pdf/textkit": "^6.0.0", + "@react-pdf/types": "^2.9.1", + "abs-svg-path": "^0.1.1", + "color-string": "^1.9.1", + "normalize-svg-path": "^1.1.0", + "parse-svg-path": "^0.1.2", + "svg-arc-to-cubic-bezier": "^3.2.0" + } + }, + "node_modules/@react-pdf/renderer": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@react-pdf/renderer/-/renderer-4.3.1.tgz", + "integrity": "sha512-dPKHiwGTaOsKqNWCHPYYrx8CDfAGsUnV4tvRsEu0VPGxuot1AOq/M+YgfN/Pb+MeXCTe2/lv6NvA8haUtj3tsA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13", + "@react-pdf/fns": "3.1.2", + "@react-pdf/font": "^4.0.3", + "@react-pdf/layout": "^4.4.1", + "@react-pdf/pdfkit": "^4.0.4", + "@react-pdf/primitives": "^4.1.1", + "@react-pdf/reconciler": "^1.1.4", + "@react-pdf/render": "^4.3.1", + "@react-pdf/types": "^2.9.1", + "events": "^3.3.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "queue": "^6.0.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@react-pdf/stylesheet": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@react-pdf/stylesheet/-/stylesheet-6.1.1.tgz", + "integrity": "sha512-Iyw0A3wRIeQLN4EkaKf8yF9MvdMxiZ8JjoyzLzDHSxnKYoOA4UGu84veCb8dT9N8MxY5x7a0BUv/avTe586Plg==", + "license": "MIT", + "dependencies": { + "@react-pdf/fns": "3.1.2", + "@react-pdf/types": "^2.9.1", + "color-string": "^1.9.1", + "hsl-to-hex": "^1.0.0", + "media-engine": "^1.0.3", + "postcss-value-parser": "^4.1.0" + } + }, + "node_modules/@react-pdf/textkit": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@react-pdf/textkit/-/textkit-6.0.0.tgz", + "integrity": "sha512-fDt19KWaJRK/n2AaFoVm31hgGmpygmTV7LsHGJNGZkgzXcFyLsx+XUl63DTDPH3iqxj3xUX128t104GtOz8tTw==", + "license": "MIT", + "dependencies": { + "@react-pdf/fns": "3.1.2", + "bidi-js": "^1.0.2", + "hyphen": "^1.6.4", + "unicode-properties": "^1.4.1" + } + }, + "node_modules/@react-pdf/types": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@react-pdf/types/-/types-2.9.1.tgz", + "integrity": "sha512-5GoCgG0G5NMgpPuHbKG2xcVRQt7+E5pg3IyzVIIozKG3nLcnsXW4zy25vG1ZBQA0jmo39q34au/sOnL/0d1A4w==", + "license": "MIT", + "dependencies": { + "@react-pdf/font": "^4.0.3", + "@react-pdf/primitives": "^4.1.1", + "@react-pdf/stylesheet": "^6.1.1" + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -2269,6 +2444,12 @@ "win32" ] }, + "node_modules/abs-svg-path": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz", + "integrity": "sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA==", + "license": "MIT" + }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -2603,6 +2784,35 @@ "dev": true, "license": "MIT" }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "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/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -2627,6 +2837,24 @@ "node": ">=8" } }, + "node_modules/brotli": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", + "license": "MIT", + "dependencies": { + "base64-js": "^1.1.2" + } + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "license": "MIT", + "dependencies": { + "pako": "~1.0.5" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -2728,6 +2956,15 @@ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -2754,9 +2991,18 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -2813,6 +3059,12 @@ "node": ">= 8" } }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "license": "MIT" + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -3003,6 +3255,12 @@ "node": ">=8" } }, + "node_modules/dfa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==", + "license": "MIT" + }, "node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -3047,6 +3305,12 @@ "dev": true, "license": "MIT" }, + "node_modules/emoji-regex-xs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz", + "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==", + "license": "MIT" + }, "node_modules/enhanced-resolve": { "version": "5.18.3", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", @@ -3680,11 +3944,19 @@ "node": ">=0.10.0" } }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-glob": { @@ -3843,6 +4115,23 @@ } } }, + "node_modules/fontkit": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz", + "integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==", + "license": "MIT", + "dependencies": { + "@swc/helpers": "^0.5.12", + "brotli": "^1.3.2", + "clone": "^2.1.2", + "dfa": "^1.2.0", + "fast-deep-equal": "^3.1.3", + "restructure": "^3.0.0", + "tiny-inflate": "^1.0.3", + "unicode-properties": "^1.4.0", + "unicode-trie": "^2.0.0" + } + }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", @@ -4196,6 +4485,21 @@ "react-is": "^16.7.0" } }, + "node_modules/hsl-to-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-to-hex/-/hsl-to-hex-1.0.0.tgz", + "integrity": "sha512-K6GVpucS5wFf44X0h2bLVRDsycgJmf9FF2elg+CrqD8GcFU8c6vYhgXn8NjUkFCwj+xDFb70qgLbTUm6sxwPmA==", + "license": "MIT", + "dependencies": { + "hsl-to-rgb-for-reals": "^1.1.0" + } + }, + "node_modules/hsl-to-rgb-for-reals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/hsl-to-rgb-for-reals/-/hsl-to-rgb-for-reals-1.1.1.tgz", + "integrity": "sha512-LgOWAkrN0rFaQpfdWBQlv/VhkOxb5AsBjk6NQVx4yEzWS923T07X0M1Y0VNko2H52HeSpZrZNNMJ0aFqsdVzQg==", + "license": "ISC" + }, "node_modules/husky": { "version": "9.1.7", "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", @@ -4212,6 +4516,12 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/hyphen": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/hyphen/-/hyphen-1.10.6.tgz", + "integrity": "sha512-fXHXcGFTXOvZTSkPJuGOQf5Lv5T/R2itiiCVPg9LxAje5D00O0pP83yJShFq5V89Ly//Gt6acj7z8pbBr34stw==", + "license": "ISC" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -4248,6 +4558,12 @@ "node": ">=0.8.19" } }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, "node_modules/inputmask": { "version": "5.0.9", "resolved": "https://registry.npmjs.org/inputmask/-/inputmask-5.0.9.tgz", @@ -4630,6 +4946,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "license": "MIT" + }, "node_modules/is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", @@ -4708,6 +5030,15 @@ "node": ">= 0.4" } }, + "node_modules/jay-peg": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/jay-peg/-/jay-peg-1.1.1.tgz", + "integrity": "sha512-D62KEuBxz/ip2gQKOEhk/mx14o7eiFRaU+VNNSP4MOiIkwb/D6B3G1Mfas7C/Fit8EsSV2/IWjZElx/Gs6A4ww==", + "license": "MIT", + "dependencies": { + "restructure": "^3.0.0" + } + }, "node_modules/jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", @@ -5110,6 +5441,25 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/linebreak": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz", + "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==", + "license": "MIT", + "dependencies": { + "base64-js": "0.0.8", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/linebreak/node_modules/base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -5182,6 +5532,12 @@ "node": ">= 0.4" } }, + "node_modules/media-engine": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/media-engine/-/media-engine-1.0.3.tgz", + "integrity": "sha512-aa5tG6sDoK+k70B9iEX1NeyfT8ObCKhNDs6lJVpwF6r8vhUfuKMslIcirq6HIUYuuUYLefcEQOn9bSBOvawtwg==", + "license": "MIT" + }, "node_modules/memoize-one": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", @@ -5392,6 +5748,15 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/normalize-svg-path": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-1.1.0.tgz", + "integrity": "sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg==", + "license": "MIT", + "dependencies": { + "svg-arc-to-cubic-bezier": "^3.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -5582,6 +5947,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -5612,6 +5983,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-svg-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz", + "integrity": "sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==", + "license": "MIT" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -5705,6 +6082,12 @@ "node": "^10 || ^12 || >=14" } }, + "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==", + "license": "MIT" + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -5764,6 +6147,15 @@ "node": ">=6" } }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.3" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -5970,6 +6362,15 @@ "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==", "license": "MIT" }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.11", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", @@ -6009,6 +6410,12 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/restructure": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz", + "integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==", + "license": "MIT" + }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -6064,6 +6471,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "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/safe-push-apply": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", @@ -6309,6 +6736,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "license": "MIT" + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -6348,6 +6790,15 @@ "node": ">= 0.4" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string.prototype.includes": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", @@ -6538,6 +6989,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg-arc-to-cubic-bezier": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz", + "integrity": "sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==", + "license": "ISC" + }, "node_modules/swr": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.6.tgz", @@ -6588,6 +7045,12 @@ "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==", "license": "MIT" }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", + "license": "MIT" + }, "node_modules/tiny-warning": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", @@ -6836,6 +7299,32 @@ "dev": true, "license": "MIT" }, + "node_modules/unicode-properties": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "license": "MIT", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/unicode-trie/node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", + "license": "MIT" + }, "node_modules/unrs-resolver": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", @@ -6916,6 +7405,26 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.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==", + "license": "MIT" + }, + "node_modules/vite-compatible-readable-stream": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/vite-compatible-readable-stream/-/vite-compatible-readable-stream-3.6.1.tgz", + "integrity": "sha512-t20zYkrSf868+j/p31cRIGN28Phrjm3nRSLR2fyc2tiWi4cZGVdv68yNlwnIINTkMTmPoMiSlc0OadaO7DXZaQ==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -7053,6 +7562,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yoga-layout": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/yoga-layout/-/yoga-layout-3.2.1.tgz", + "integrity": "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==", + "license": "MIT" + }, "node_modules/yup": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/yup/-/yup-1.7.1.tgz", diff --git a/package.json b/package.json index c2f4f4e6..3416a673 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "format": "prettier --write ." }, "dependencies": { + "@react-pdf/renderer": "^4.3.1", "@tanstack/match-sorter-utils": "^8.19.4", "@tanstack/react-table": "^8.21.3", "axios": "^1.12.2", @@ -48,4 +49,4 @@ "tailwindcss": "^4", "typescript": "^5" } -} +} \ No newline at end of file diff --git a/src/app/marketing/sales-orders/detail/edit/layout.tsx b/src/app/marketing/add/delivery-orders/layout.tsx similarity index 100% rename from src/app/marketing/sales-orders/detail/edit/layout.tsx rename to src/app/marketing/add/delivery-orders/layout.tsx diff --git a/src/app/marketing/sales-orders/detail/edit/delivery/page.tsx b/src/app/marketing/add/delivery-orders/page.tsx similarity index 84% rename from src/app/marketing/sales-orders/detail/edit/delivery/page.tsx rename to src/app/marketing/add/delivery-orders/page.tsx index 3a5f7a91..4d92acda 100644 --- a/src/app/marketing/sales-orders/detail/edit/delivery/page.tsx +++ b/src/app/marketing/add/delivery-orders/page.tsx @@ -1,16 +1,17 @@ 'use client'; -import SalesForm from '@/components/pages/marketing/form/MarketingForm'; +import MarketingForm from '@/components/pages/marketing/form/MarketingForm'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; import { MarketingApi } from '@/services/api/marketing/marketing'; import { useRouter, useSearchParams } from 'next/navigation'; +import toast from 'react-hot-toast'; import useSWR from 'swr'; const EditMarketingDelivery = () => { const router = useRouter(); const searchParams = useSearchParams(); - const soId = searchParams.get('salesOrderId'); + const soId = searchParams.get('marketingId'); const { data: marketing, @@ -34,12 +35,13 @@ const EditMarketingDelivery = () => { router.replace('/404'); return; } + return (
{isLoading && } {!isLoading && isResponseSuccess(marketing) && ( - { refreshMarketing(); diff --git a/src/app/marketing/sales-orders/add/page.tsx b/src/app/marketing/add/sales-orders/page.tsx similarity index 52% rename from src/app/marketing/sales-orders/add/page.tsx rename to src/app/marketing/add/sales-orders/page.tsx index 8d64e66d..9e33d304 100644 --- a/src/app/marketing/sales-orders/add/page.tsx +++ b/src/app/marketing/add/sales-orders/page.tsx @@ -1,9 +1,9 @@ -import SalesForm from '@/components/pages/marketing/form/MarketingForm'; +import MarketingForm from '@/components/pages/marketing/form/MarketingForm'; const AddSalesOrder = () => { return (
- +
); }; diff --git a/src/app/marketing/sales-orders/detail/layout.tsx b/src/app/marketing/detail/delivery-orders/edit/layout.tsx similarity index 100% rename from src/app/marketing/sales-orders/detail/layout.tsx rename to src/app/marketing/detail/delivery-orders/edit/layout.tsx diff --git a/src/app/marketing/detail/delivery-orders/edit/page.tsx b/src/app/marketing/detail/delivery-orders/edit/page.tsx new file mode 100644 index 00000000..32625026 --- /dev/null +++ b/src/app/marketing/detail/delivery-orders/edit/page.tsx @@ -0,0 +1,62 @@ +'use client'; + +import MarketingForm from '@/components/pages/marketing/form/MarketingForm'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; +import { MarketingApi } from '@/services/api/marketing/marketing'; +import { useRouter, useSearchParams } from 'next/navigation'; +import toast from 'react-hot-toast'; +import useSWR from 'swr'; + +const EditMarketingDelivery = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const soId = searchParams.get('marketingId'); + + const { + data: marketing, + isLoading: isLoading, + mutate: refreshMarketing, + } = useSWR(`get-so-${soId}`, () => + MarketingApi.getSingle(soId ? parseInt(soId) : 0) + ); + + if (!soId) { + router.back(); + + return ( +
+ +
+ ); + } + + if (!isLoading && (!marketing || isResponseError(marketing))) { + router.replace('/404'); + return; + } + + if ( + isResponseSuccess(marketing) && + marketing.data.latest_approval.step_number != 3 + ) { + toast.error('Data Marketing perlu dilakukan approval terlebih dahulu!'); + router.back(); + } + + return ( +
+ {isLoading && } + {!isLoading && isResponseSuccess(marketing) && ( + { + refreshMarketing(); + }} + /> + )} +
+ ); +}; +export default EditMarketingDelivery; diff --git a/src/app/marketing/detail/layout.tsx b/src/app/marketing/detail/layout.tsx new file mode 100644 index 00000000..7220dfa1 --- /dev/null +++ b/src/app/marketing/detail/layout.tsx @@ -0,0 +1,11 @@ +import SuspenseHelper from '@/components/helper/SuspenseHelper'; + +const Layout = ({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) => { + return {children}; +}; + +export default Layout; diff --git a/src/app/marketing/sales-orders/detail/page.tsx b/src/app/marketing/detail/page.tsx similarity index 82% rename from src/app/marketing/sales-orders/detail/page.tsx rename to src/app/marketing/detail/page.tsx index ca08f41b..902251e8 100644 --- a/src/app/marketing/sales-orders/detail/page.tsx +++ b/src/app/marketing/detail/page.tsx @@ -1,16 +1,16 @@ 'use client'; -import SalesOrderDetail from '@/components/pages/marketing/detail/MarketingDetail'; +import MarketingDetail from '@/components/pages/marketing/detail/MarketingDetail'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; import { MarketingApi } from '@/services/api/marketing/marketing'; import { useRouter, useSearchParams } from 'next/navigation'; import useSWR from 'swr'; -const DetailSalesOrder = () => { +const DetailMarketing = () => { const router = useRouter(); const searchParams = useSearchParams(); - const soId = searchParams.get('salesOrderId'); + const soId = searchParams.get('marketingId'); const { data: marketing, @@ -37,7 +37,7 @@ const DetailSalesOrder = () => {
{isLoading && } {!isLoading && isResponseSuccess(marketing) && ( - @@ -46,4 +46,4 @@ const DetailSalesOrder = () => { ); }; -export default DetailSalesOrder; +export default DetailMarketing; diff --git a/src/app/marketing/detail/sales-orders/edit/layout.tsx b/src/app/marketing/detail/sales-orders/edit/layout.tsx new file mode 100644 index 00000000..7220dfa1 --- /dev/null +++ b/src/app/marketing/detail/sales-orders/edit/layout.tsx @@ -0,0 +1,11 @@ +import SuspenseHelper from '@/components/helper/SuspenseHelper'; + +const Layout = ({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) => { + return {children}; +}; + +export default Layout; diff --git a/src/app/marketing/sales-orders/detail/edit/page.tsx b/src/app/marketing/detail/sales-orders/edit/page.tsx similarity index 89% rename from src/app/marketing/sales-orders/detail/edit/page.tsx rename to src/app/marketing/detail/sales-orders/edit/page.tsx index d05f4d39..19a098c5 100644 --- a/src/app/marketing/sales-orders/detail/edit/page.tsx +++ b/src/app/marketing/detail/sales-orders/edit/page.tsx @@ -1,6 +1,6 @@ 'use client'; -import SalesForm from '@/components/pages/marketing/form/MarketingForm'; +import MarketingForm from '@/components/pages/marketing/form/MarketingForm'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; import { MarketingApi } from '@/services/api/marketing/marketing'; import { useRouter, useSearchParams } from 'next/navigation'; @@ -10,7 +10,7 @@ const EditSalesOrder = () => { const router = useRouter(); const searchParams = useSearchParams(); - const soId = searchParams.get('salesOrderId'); + const soId = searchParams.get('marketingId'); const { data: marketing, @@ -38,7 +38,7 @@ const EditSalesOrder = () => {
{isLoading && } {!isLoading && isResponseSuccess(marketing) && ( - { diff --git a/src/app/marketing/page.tsx b/src/app/marketing/page.tsx new file mode 100644 index 00000000..99a80b64 --- /dev/null +++ b/src/app/marketing/page.tsx @@ -0,0 +1,10 @@ +import MarketingTable from '@/components/pages/marketing/MarketingTable'; + +const Marketing = () => { + return ( +
+ +
+ ); +}; +export default Marketing; diff --git a/src/app/marketing/sales-orders/page.tsx b/src/app/marketing/sales-orders/page.tsx deleted file mode 100644 index 427db57d..00000000 --- a/src/app/marketing/sales-orders/page.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import SalesOrderTable from '@/components/pages/marketing/MarketingTable'; - -const SalesOrder = () => { - return ( -
- -
- ); -}; -export default SalesOrder; diff --git a/src/components/pages/marketing/MarketingTable.tsx b/src/components/pages/marketing/MarketingTable.tsx index 2bad4c97..e253fe39 100644 --- a/src/components/pages/marketing/MarketingTable.tsx +++ b/src/components/pages/marketing/MarketingTable.tsx @@ -22,6 +22,7 @@ import { useTableFilter } from '@/services/hooks/useTableFilter'; import { BaseSalesOrder, Marketing } from '@/types/api/marketing/marketing'; import { Icon } from '@iconify/react'; import { CellContext, Row } from '@tanstack/react-table'; +import { useRouter } from 'next/navigation'; import { useCallback, useState } from 'react'; import toast from 'react-hot-toast'; import useSWR from 'swr'; @@ -30,10 +31,12 @@ const RowsOptionsMenu = ({ type = 'dropdown', props, deleteClickHandler, + deliveryClickHandler, }: { type: 'dropdown' | 'collapse'; props: CellContext; deleteClickHandler: () => void; + deliveryClickHandler?: () => void; }) => { return (
+ @@ -407,7 +400,7 @@ const SalesOrderDetail = ({
- - {/*
{JSON.stringify(initialValues)}
+ {(formType == 'add' || formType == 'edit') && ( + + {/*
{JSON.stringify(initialValues)}
{JSON.stringify(formik.values)}
{JSON.stringify(formik.errors)}
*/} - -
- {formType == 'deliver' && + +
+ )} + {(formType == 'add_deliver' || formType == 'edit_deliver') && initialValues?.sales_order && initialValues?.sales_order.length > 0 && ( - {/* {JSON.stringify(memoSalesOrder)} - {JSON.stringify(memoDeliveryOrder)} */} - {JSON.stringify(memoDeliveryOrder)} */} + {/* + {JSON.stringify(formik.errors)} + */} + )} @@ -556,7 +643,7 @@ const SalesForm = ({ onChange={formik.handleChange} isError={formik.touched.notes && Boolean(formik.errors.notes)} errorMessage={formik.errors.notes} - disabled={formType === 'deliver'} + disabled={formType === 'add_deliver' || formType === 'edit_deliver'} />
Total Penjualan @@ -611,7 +698,7 @@ const SalesForm = ({
- @@ -640,7 +727,7 @@ const SalesForm = ({
- { setFormErrorMessage(''); if (initialValues?.id) { @@ -172,42 +172,21 @@ const DeliveryOrderProductForm = ({ )}
- - - - item.id === selectedProduct?.value + )?.product_warehouse.product.name, + } as OptionType) + : null + } onChange={(value) => { const selected = value as OptionType; setSelectedProduct(selected); @@ -263,6 +242,36 @@ const DeliveryOrderProductForm = ({ errorMessage={formik.errors.marketing_product_id} required /> + + +
)} + {/* + {JSON.stringify(formik.errors)} + */}
; setRowSelection: React.Dispatch< React.SetStateAction> @@ -27,6 +28,7 @@ type DeliveryOrderProductTableProps = { onEdit: (id: number) => void; onBulkDelete: () => void; onAddProductClick: () => void; + onInputDate: (data: DeliveryOrderProductFormValues) => void; }; const DeliveryOrderProductTable = ({ @@ -40,6 +42,7 @@ const DeliveryOrderProductTable = ({ onEdit, onBulkDelete, onAddProductClick, + onInputDate, }: DeliveryOrderProductTableProps) => { const onDeleteRef = useRef(onDelete); const onEditRef = useRef(onDelete); @@ -53,51 +56,86 @@ const DeliveryOrderProductTable = ({ return acc && deliveredQty.length != salesOrder.length; }, true); - const columns = useMemo( - () => [ - { - id: 'select', - header: ({ - table, - }: { - table: TanStack.Table; - }) => ( -
- -
- ), - cell: ({ - row, - }: { - row: TanStack.Row; - }) => ( -
- -
- ), - }, + const columns = useMemo(() => { + const cols = [ + // { + // id: 'select', + // header: ({ + // table, + // }: { + // table: TanStack.Table; + // }) => ( + //
+ // + //
+ // ), + // cell: ({ + // row, + // }: { + // row: TanStack.Row; + // }) => ( + //
+ // + //
+ // ), + // }, { accessorFn: (row: DeliveryOrderProductFormValues) => row.do_number, header: 'No. Pengiriman', cell: ( props: TanStack.CellContext - ) => props.row.original.do_number ?? '-', + ) =>
{props.row.original.do_number}
, }, { accessorFn: (row: DeliveryOrderProductFormValues) => - formatDate(row.delivery_date as string, 'DD MMM YYYY'), + row.delivery_date + ? formatDate(row.delivery_date as string, 'DD MMM YYYY') + : '-', header: 'Tanggal Delivery', + cell: ( + props: TanStack.CellContext + ) => ( + <> + {formType == 'add_deliver' && ( + { + onInputDate({ + ...props.row.original, + delivery_date: val.target.value, + }); + }} + /> + )} + + {formType == 'edit_deliver' && + formatDate( + props.row.original.delivery_date as string, + 'DD MMM YYYY' + )} + + ), }, { accessorFn: (row: DeliveryOrderProductFormValues) => @@ -145,30 +183,39 @@ const DeliveryOrderProductTable = ({ props: TanStack.CellContext ) => (
- - + <> + + {/* */} +
), }, - ], - [] - ); + ]; + if (formType == 'add_deliver') { + return cols.filter( + (col) => col.header != 'Aksi' && col.header != 'No. Pengiriman' + ); + } + return cols; + }, [formType, onInputDate, onEditRef]); return ( <> @@ -185,7 +232,7 @@ const DeliveryOrderProductTable = ({ 'px-2 py-2 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end first:flex first:flex-row first:justify-start', bodyRowClassName: 'border-b border-b-gray-200', bodyColumnClassName: - 'px-2 py-2 last:flex last:flex-row last:justify-end first:flex first:flex-row first:justify-start', + 'px-2 py-2 last:flex last:flex-row last:justify-end', paginationClassName: 'hidden', }} emptyContent={ @@ -199,16 +246,16 @@ const DeliveryOrderProductTable = ({ } />
- + */} {selectedRowIds.length > 0 && ( + ) : null; +}; + +export default SalesOrderExport; +const PDFDocument = ({ data }: { data: Marketing }) => { + const grandTotal = useMemo(() => { + return data?.sales_order?.reduce((a, b) => a + b.total_price, 0) ?? 0; + }, [data?.sales_order]); + + return ( + + + {/* Header Section */} + + + PT LUMBUNG TELUR INDONESIA + + SOHO Building Lt.3 (Paris Van Java), Jalan Karang Tinggal, Kel. + Cipedes, Kec. Sukajadi, Kota Bandung 40162 + + + + + {/* Sales Order Title */} + + SALES ORDER + + SO Number: {data?.so_number || '-'} + + Date:{' '} + {data?.so_date + ? formatDate(data.so_date, 'DD MMM YYYY') + : formatDate(new Date(), 'DD MMM YYYY')} + + + + + {/* Customer Table */} + + + + Customer + + + Sales + + + + + + {data?.customer?.name || '-'} ({data?.customer?.type || '-'}) + + + {data?.customer.email || ''} - {data?.customer.phone || ''} + + + {data?.customer.address || ''} + + + + + PT LUMBUNG TELUR INDONESIA + + + {data?.sales_person?.name || '-'} + + {data?.sales_person.email} + + + + + {/* Product Sales Order Table */} + Product Sold + + + + Item Description + + + From + + + Unit Price + + + Quantity + + + Total Amount + + + {data?.sales_order?.map((item, index) => { + const isLastItem = index === (data?.sales_order?.length || 0) - 1; + return ( + + + {item.product_warehouse?.product?.name || '-'} + + + {item.product_warehouse?.warehouse?.name || '-'} + + + Rp{formatNumber(item.unit_price || 0)} + + + {formatNumber(item.qty || 0)} + + + Rp{formatNumber(item.total_price || 0)} + + + ); + }) || []} + + {/* Grand Total Row inside table */} + + + + + + + + + + + + Grand Total + + + Rp{formatNumber(grandTotal)} + + + + + {/* Footer with Special Instructions */} + + + + + Notes + + + + + {data?.notes || '-'} + + + + + PT LUMBUNG TELUR INDONESIA + + + + + ); +}; diff --git a/src/components/pages/marketing/pdf/styles/MarketingPDFStyles.tsx b/src/components/pages/marketing/pdf/styles/MarketingPDFStyles.tsx new file mode 100644 index 00000000..3a0aa5c7 --- /dev/null +++ b/src/components/pages/marketing/pdf/styles/MarketingPDFStyles.tsx @@ -0,0 +1,212 @@ +import { StyleSheet } from '@react-pdf/renderer'; + +const pdfStyles = StyleSheet.create({ + page: { + fontSize: 10, + fontFamily: 'Helvetica', + padding: 20, + backgroundColor: '#FFFFFF', + }, + header: { + marginBottom: 20, + }, + logo: { + width: 120, + height: 30, + marginBottom: 8, + }, + companyInfo: { + fontSize: 12, + fontWeight: 'bold', + marginBottom: 4, + color: '#1f74bf', + }, + address: { + fontSize: 8, + color: '#666666', + maxWidth: 400, + marginBottom: 10, + }, + divider: { + borderBottomWidth: 1, + borderBottomColor: '#000000', + borderBottomStyle: 'solid', + marginBottom: 15, + }, + titleSection: { + flexDirection: 'row', + marginBottom: 20, + justifyContent: 'space-between', + alignItems: 'flex-start', + }, + title: { + fontSize: 18, + fontWeight: 'bold', + flex: 3, + color: '#1f74bf', + }, + poInfo: { + flex: 1, + fontSize: 9, + textAlign: 'right', + }, + sectionTitle: { + fontSize: 12, + fontWeight: 'bold', + marginBottom: 8, + color: '#1f74bf', + }, + table: { + borderWidth: 1, + borderColor: '#000000', + marginBottom: 15, + }, + tableRow: { + flexDirection: 'row', + }, + tableHeader: { + backgroundColor: '#F5F5F5', + }, + tableCell: { + flex: 1, + borderRightWidth: 1, + borderRightColor: '#000000', + borderRightStyle: 'solid', + padding: 8, + fontSize: 9, + }, + tableCellLast: { + flex: 1, + padding: 8, + fontSize: 9, + }, + tableCellHeader: { + flex: 1, + borderRightWidth: 1, + borderRightColor: '#000000', + borderRightStyle: 'solid', + padding: 8, + fontSize: 9, + fontWeight: 'bold', + backgroundColor: '#F5F5F5', + }, + tableCellHeaderLast: { + flex: 1, + padding: 8, + fontSize: 9, + fontWeight: 'bold', + backgroundColor: '#F5F5F5', + }, + tableCellRight: { + flex: 1, + borderRightWidth: 1, + borderRightColor: '#000000', + borderRightStyle: 'solid', + padding: 8, + fontSize: 9, + textAlign: 'right', + }, + tableCellRightLast: { + flex: 1, + padding: 8, + fontSize: 9, + textAlign: 'right', + }, + tableBorderBottom: { + borderBottomWidth: 1, + borderBottomColor: '#000000', + borderBottomStyle: 'solid', + }, + grandTotalRow: { + flexDirection: 'row', + borderTopWidth: 1, + borderTopColor: '#000000', + borderTopStyle: 'solid', + }, + grandTotalLabel: { + flex: 3, + padding: 8, + fontSize: 9, + fontWeight: 'bold', + textAlign: 'right', + borderRightWidth: 1, + borderRightColor: '#000000', + borderRightStyle: 'solid', + }, + grandTotalValue: { + flex: 1, + padding: 8, + fontSize: 9, + fontWeight: 'bold', + textAlign: 'right', + borderRightWidth: 0, + }, + allocationSection: { + marginBottom: 15, + }, + allocationTable: { + borderWidth: 1, + borderColor: '#000000', + }, + innerTable: { + marginTop: 5, + borderWidth: 1, + borderColor: '#000000', + }, + innerRow: { + flexDirection: 'row', + borderBottomWidth: 1, + borderBottomColor: '#000000', + borderBottomStyle: 'solid', + }, + innerCell: { + flex: 1, + borderRightWidth: 1, + borderRightColor: '#000000', + borderRightStyle: 'solid', + padding: 8, + fontSize: 9, + }, + innerCellLast: { + flex: 1, + padding: 8, + fontSize: 9, + }, + innerCellRight: { + flex: 1, + borderRightWidth: 1, + borderRightColor: '#000000', + borderRightStyle: 'solid', + padding: 8, + fontSize: 9, + textAlign: 'right', + }, + innerCellRightLast: { + flex: 1, + padding: 8, + fontSize: 9, + textAlign: 'right', + }, + footer: { + marginTop: 30, + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'flex-start', + }, + footerCompany: { + fontSize: 12, + fontWeight: 'bold', + textAlign: 'right', + flex: 1, + color: '#1f74bf', + }, + specialInstructionTable: { + width: '60%', + maxWidth: 300, + borderWidth: 1, + borderColor: '#000000', + flex: 1, + }, +}); + +export default pdfStyles; diff --git a/src/config/constant.ts b/src/config/constant.ts index e82a1e7b..f2da02a6 100644 --- a/src/config/constant.ts +++ b/src/config/constant.ts @@ -48,7 +48,7 @@ export const MAIN_DRAWER_LINKS: MAIN_DRAWER_MENU[] = [ { title: 'Penjualan', - link: '/marketing/sales-orders', + link: '/marketing', icon: 'mdi:attach-money', },