diff --git a/global.d.ts b/global.d.ts new file mode 100644 index 0000000..fd1a119 --- /dev/null +++ b/global.d.ts @@ -0,0 +1,17 @@ +// global.d.ts +import { IStaticMethods } from "flyonui/flyonui"; + +declare global { + interface Window { + // Optional third-party libraries + _; + $: typeof import("jquery"); + jQuery: typeof import("jquery"); + DataTable; + Dropzone; + + HSStaticMethods: IStaticMethods; + } +} + +export {}; diff --git a/package-lock.json b/package-lock.json index b4352cb..a9552df 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,15 +9,20 @@ "version": "0.1.0", "dependencies": { "@sumup/sdk": "^0.0.4", + "flyonui": "^2.4.0", "next": "15.5.3", "react": "19.1.0", - "react-dom": "19.1.0" + "react-dom": "19.1.0", + "ws": "^8.18.3" }, "devDependencies": { + "@iconify-json/tabler": "^1.2.23", + "@iconify/tailwind4": "^1.0.6", "@tailwindcss/postcss": "^4", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", + "@types/ws": "^8.18.1", "tailwindcss": "^4", "typescript": "^5" } @@ -35,6 +40,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@antfu/utils": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-8.1.1.tgz", + "integrity": "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@emnapi/runtime": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", @@ -45,6 +74,82 @@ "tslib": "^2.4.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", + "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@iconify-json/tabler": { + "version": "1.2.23", + "resolved": "https://registry.npmjs.org/@iconify-json/tabler/-/tabler-1.2.23.tgz", + "integrity": "sha512-Knb8ykgMwB5uSoqrDv1xIdJYM03OP06OXjN6QvGXaTNtdHkW9ciKA+aftz6lwM2jwJA+bsUWeDzLBlPt2uJm4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@iconify/types": "*" + } + }, + "node_modules/@iconify/tailwind4": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@iconify/tailwind4/-/tailwind4-1.0.6.tgz", + "integrity": "sha512-43ZXe+bC7CuE2LCgROdqbQeFYJi/J7L/k1UpSy8KDQlWVsWxPzLSWbWhlJx4uRYLOh1NRyw02YlDOgzBOFNd+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@iconify/types": "^2.0.0", + "@iconify/utils": "^2.2.1" + }, + "funding": { + "url": "https://github.com/sponsors/cyberalien" + }, + "peerDependencies": { + "tailwindcss": ">= 4" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@iconify/utils": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.3.0.tgz", + "integrity": "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@antfu/install-pkg": "^1.0.0", + "@antfu/utils": "^8.1.0", + "@iconify/types": "^2.0.0", + "debug": "^4.4.0", + "globals": "^15.14.0", + "kolorist": "^1.8.0", + "local-pkg": "^1.0.0", + "mlly": "^1.7.4" + } + }, "node_modules/@img/colour": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", @@ -994,6 +1099,29 @@ "@types/react": "^19.0.0" } }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001743", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001743.tgz", @@ -1030,6 +1158,13 @@ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "dev": true, + "license": "MIT" + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -1037,6 +1172,24 @@ "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/detect-libc": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.0.tgz", @@ -1061,6 +1214,35 @@ "node": ">=10.13.0" } }, + "node_modules/exsolve": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", + "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/flyonui": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/flyonui/-/flyonui-2.4.0.tgz", + "integrity": "sha512-gXlZLY1/XcywnitWCB4EVbUNU8NSA92RRyi5WGRK5wyQunQEHRW/AvTUyZoiNIxjVC/VRnnO0vkLPsETXsj9RQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.1" + } + }, + "node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -1078,6 +1260,13 @@ "jiti": "lib/jiti-cli.mjs" } }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lightningcss": { "version": "1.30.1", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", @@ -1317,6 +1506,24 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/local-pkg": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.2.tgz", + "integrity": "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mlly": "^1.7.4", + "pkg-types": "^2.3.0", + "quansync": "^0.2.11" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/magic-string": { "version": "0.30.19", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", @@ -1366,6 +1573,45 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/mlly": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.1" + } + }, + "node_modules/mlly/node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/mlly/node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "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/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -1464,12 +1710,38 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/package-manager-detector": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.3.0.tgz", + "integrity": "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "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==", "license": "ISC" }, + "node_modules/pkg-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -1499,6 +1771,23 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/quansync": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", + "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, "node_modules/react": { "version": "19.1.0", "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", @@ -1653,6 +1942,13 @@ "node": ">=18" } }, + "node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "dev": true, + "license": "MIT" + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -1673,6 +1969,13 @@ "node": ">=14.17" } }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "dev": true, + "license": "MIT" + }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", @@ -1680,6 +1983,27 @@ "dev": true, "license": "MIT" }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/yallist": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", diff --git a/package.json b/package.json index f60e1b1..1870015 100644 --- a/package.json +++ b/package.json @@ -9,15 +9,20 @@ }, "dependencies": { "@sumup/sdk": "^0.0.4", + "flyonui": "^2.4.0", "next": "15.5.3", "react": "19.1.0", - "react-dom": "19.1.0" + "react-dom": "19.1.0", + "ws": "^8.18.3" }, "devDependencies": { + "@iconify-json/tabler": "^1.2.23", + "@iconify/tailwind4": "^1.0.6", "@tailwindcss/postcss": "^4", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", + "@types/ws": "^8.18.1", "tailwindcss": "^4", "typescript": "^5" } diff --git a/src/actions/add-to-cart.tsx b/src/actions/add-to-cart.tsx index d546e88..4755e62 100644 --- a/src/actions/add-to-cart.tsx +++ b/src/actions/add-to-cart.tsx @@ -19,8 +19,20 @@ const addToCart = async (barcode: number) => { 'GROCY-API-KEY': "VCPlNborGO2t8rs08cvqodalf3AjecRwgexWzkIk221mtshLoM" } }); + const userfields = await request2.json(); - console.log(`Price of product ${data.product.name} is ${userfields.kuelschrankpreis} EUR`); - return {name: data.product.name, price: userfields.kuelschrankpreis}; + + if ( data.product.picture_file_name ) { + const image_fetch = await fetch(`https://development.vonhelmersen.online/api/files/productpictures/${btoa(data.product.picture_file_name)}`, { + method: 'GET', + headers: { + 'accept': "application/octet-stream", + 'GROCY-API-KEY': "VCPlNborGO2t8rs08cvqodalf3AjecRwgexWzkIk221mtshLoM" + }}); + const img_blob = await image_fetch.blob() + return {name: data.product.name, price: userfields.kuelschrankpreis, img_blob: img_blob}; + } else { + return {name: data.product.name, price: userfields.kuelschrankpreis}; + } } export default addToCart; diff --git a/src/actions/checkout.tsx b/src/actions/checkout.tsx index 4a4ea37..5ca3cad 100644 --- a/src/actions/checkout.tsx +++ b/src/actions/checkout.tsx @@ -1,6 +1,7 @@ "use server" const API_KEY = "sup_sk_t6Jf0FwYUAkbjxzvbs6e3BkIePxm0OR3m" +const HOSTNAME = "kasse.fet.at" import SumUp from "@sumup/sdk"; @@ -13,10 +14,12 @@ const checkout = async (total: number) => { const merchantCode = (await client.merchant.getMerchantProfile()).merchant_code || ""; const readerId = (await client.readers.list(merchantCode)).items[0].id || ""; - const respomse = await client.readers.createCheckout(merchantCode, readerId, {total_amount: {value: total * 100, currency: "EUR", minor_unit: 2}}); + const response = await client.readers.createCheckout(merchantCode, readerId, { + total_amount: {value: total * 100, currency: "EUR", minor_unit: 2}, + return_url: `https://${HOSTNAME}/order-status` + }); await new Promise(resolve => setTimeout(resolve, 10000)); - const checkout = await client.transactions.get(merchantCode, {client_transaction_id: respomse.data?.client_transaction_id || ""}); - console.log("Checkout status:", checkout); + return response.data?.client_transaction_id || ""; } export default checkout; diff --git a/src/app/api/order-status/route.ts b/src/app/api/order-status/route.ts new file mode 100644 index 0000000..cd9edad --- /dev/null +++ b/src/app/api/order-status/route.ts @@ -0,0 +1,57 @@ +// app/api/order-status/[id]/route.ts +import { NextRequest, NextResponse } from "next/server"; +import { EventEmitter } from "stream"; + +export const orderEvents = new EventEmitter(); + +export async function GET(req: NextRequest) { + // const orderId = params.id; + const orderId = req.nextUrl.searchParams.get("id"); + + return new Response( + new ReadableStream({ + start(controller) { + const encoder = new TextEncoder(); + + const listener = (data: { id: string; event_type: string }) => { + // TODO!!!! UNCOMMEND THIS + // if (data.orderId != orderId) { + // return; + // } + console.error("THIS SHOULD BE UNCOMMENTED"); + console.log("Sending event:", data); + controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\n\n`)); + }; + + // orderEvents.on("update", listener); + orderEvents.addListener("update", listener); + + // cleanup when client disconnects + req.signal.addEventListener("abort", () => { + orderEvents.off("update", listener); + controller.close(); + }); + }, + }), + { + headers: { + "Content-Type": "text/event-stream", + "Cache-Control": "no-cache", + Connection: "keep-alive", + }, + } + ); +} + + +export async function POST(req: NextRequest) { + + const body = await req.json(); + console.log("Webhook received:", body); + const event_type = body.event_type || ""; + const id = body.id || ""; + + orderEvents.emit("update", { id, event_type }); + + return NextResponse.json({ message: 'Webhook received' }); +} diff --git a/src/app/globals.css b/src/app/globals.css index a2dc41e..75ff022 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,26 +1,11 @@ @import "tailwindcss"; +@plugin "flyonui"; +@import "flyonui/variants.css"; +@plugin "@iconify/tailwind4"; +@source "./node_modules/flyonui/flyonui.js"; :root { --background: #ffffff; --foreground: #171717; } -@theme inline { - --color-background: var(--background); - --color-foreground: var(--foreground); - --font-sans: var(--font-geist-sans); - --font-mono: var(--font-geist-mono); -} - -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } -} - -body { - background: var(--background); - color: var(--foreground); - font-family: Arial, Helvetica, sans-serif; -} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index f7fa87e..1fbe042 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; +import { Geist, Geist_Mono, Inter_Tight } from "next/font/google"; import "./globals.css"; +import FlyonuiScript from '../components/FlyonuiScript'; const geistSans = Geist({ variable: "--font-geist-sans", @@ -24,11 +25,15 @@ export default function RootLayout({ }>) { return ( - - {children} - + +
+
+

Baroness

+
+ {children} +
+ + ); } diff --git a/src/app/page.tsx b/src/app/page.tsx index 128bc26..bb3e6b4 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,10 +1,20 @@ "use client" import addToCart from "@/actions/add-to-cart"; import checkout from "@/actions/checkout"; -import { useState } from "react"; +import { useEffect, useState } from "react"; + +const createTableImage = (img_blob: Blob | undefined) => { + if (!img_blob) { + return
?
+ } else { + return product image + } +} + +const quick_products = [ {name: "Cola"}, {name: "Fanta"}, {name: "Wasser"}, {name: "Red Bull"}, {name: "Bier"}, {name: "Wein"} ]; export default function Home() { - const [ cart, setCart ] = useState<{name: string, price: number}[]>([]); + const [ cart, setCart ] = useState<{name: string, price: number, img_blob?: Blob | undefined}[]>([]); const handleSubmit = async (formData: FormData) => { const barcode = formData.get("barcode")? Number(formData.get("barcode")) : 0; addToCart(barcode).then((item) => { @@ -17,25 +27,197 @@ export default function Home() { cart.forEach((item) => { total += (Number(item.price)); }); - checkout(total); - setCart([]); + const client_checkout_id = checkout(total); + setStatus("Initializing"); + window.HSOverlay.open('#transparent-modal'); } + + const [status, setStatus] = useState("NONE"); + + useEffect(() => { + const but = document.getElementById("open-modal"); + but?.addEventListener("click", () => { + window.HSOverlay.open('#failed-modal'); + }); + }, []); + + useEffect(() => { + const es = new EventSource(`/api/order-status/`); + console.log("EventSource created"); + + es.onmessage = (event) => { + const data = JSON.parse(event.data); + setStatus(data.event_type); + console.log("Received event:", data); + + switch(data.event_type) { + case "PENDING": + setStatus("Verarbeiteung..."); + break; + case "PAID": + // Order is completed + setStatus("Erfolgreich bezahlt!"); + window.HSOverlay.close('#transparent-modal') + window.HSOverlay.open('#success-modal'); + setStatus("NONE"); + setCart([]); + break; + case "FAILED": + window.HSOverlay.open('#failed-modal'); + setStatus("NONE"); + break; + default: + // Unknown event type + break; + } + }; + + return () => es.close(); + }, []); + return ( <> -

Barcode:

-
- - -
-

Cart:

- -
- -
+
+
+
+
+ + + + + + + + + + + + + + + +
Scanne den Barcode deines Produkts um es dem Warenkorb hinzuzufügen.
Überprüfe deinen Warenkorb und entferne Produkte, die du nicht kaufen möchtest.
Klicke anschließend auf Bezahlen.
Bezahlen mit Karte am Karten Terminal
+
+
+

Schnellauswahl:

+
+ {quick_products.map((item, index) => ( + + ))} +
+

Barcode:

+
+
+ + + + + +
+ +
+ +
+
+

Cart:

+ + + + + + + + + + + {cart.map((item, index) => ( + + + + + + + ))} + +
BildNamePreis
+
+ { createTableImage(item.img_blob) } +
+
{item.name}{item.price}€
+
+ +
+ +
+
+ + + + + + + ) } diff --git a/src/app/reader/page.tsx b/src/app/reader/page.tsx index d6b2708..c73f4c3 100644 --- a/src/app/reader/page.tsx +++ b/src/app/reader/page.tsx @@ -2,10 +2,15 @@ import getReaderList from "@/actions/getReaderList"; import registerReader from "@/actions/registerReader"; -import { useState } from "react"; +import { useEffect, useState } from "react"; const Page = () => { const [ readers, setReaders ] = useState(); + useEffect(() => { + getReaderList().then((readerList) => { + setReaders(readerList); + }); + }, readers); const handleRegisterReader = async (formData: FormData) => { const readername = formData.get("readername")?.toString() || ""; const pairingcode = formData.get("pairingcode")?.toString() || ""; diff --git a/src/components/FlyonuiScript.tsx b/src/components/FlyonuiScript.tsx new file mode 100644 index 0000000..9dc69a9 --- /dev/null +++ b/src/components/FlyonuiScript.tsx @@ -0,0 +1,47 @@ +// FlyonuiScript.tsx +'use client'; + +import { usePathname } from 'next/navigation'; +import { useEffect } from 'react'; + +// Optional third-party libraries +// import $ from 'jquery'; +// import _ from 'lodash'; +// import noUiSlider from 'nouislider'; +// import 'datatables.net'; +// import 'dropzone/dist/dropzone-min.js'; + +// window.$ = $; +// window._ = _; +// window.jQuery = $; +// window.DataTable = $.fn.dataTable; +// window.noUiSlider = noUiSlider; + +async function loadFlyonUI() { + return import('flyonui/flyonui'); +} + +export default function FlyonuiScript() { + const path = usePathname(); + + useEffect(() => { + const initFlyonUI = async () => { + await loadFlyonUI(); + }; + + initFlyonUI(); + }, []); + + useEffect(() => { + setTimeout(() => { + if ( + window.HSStaticMethods && + typeof window.HSStaticMethods.autoInit === 'function' + ) { + window.HSStaticMethods.autoInit(); + } + }, 100); + }, [path]); + + return null; +}