diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..e6ef4f3
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml
new file mode 100644
index 0000000..7900cc8
--- /dev/null
+++ b/.idea/dataSources.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ mysql.8
+ true
+ com.mysql.cj.jdbc.Driver
+ jdbc:mysql://localhost:3306/ticket_sys
+ $ProjectFileDir$
+
+
+
\ No newline at end of file
diff --git a/.idea/data_source_mapping.xml b/.idea/data_source_mapping.xml
new file mode 100644
index 0000000..d6749b4
--- /dev/null
+++ b/.idea/data_source_mapping.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Next_js__debug_client_side.xml b/.idea/runConfigurations/Next_js__debug_client_side.xml
new file mode 100644
index 0000000..204b1e8
--- /dev/null
+++ b/.idea/runConfigurations/Next_js__debug_client_side.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml
new file mode 100644
index 0000000..56782ca
--- /dev/null
+++ b/.idea/sqldialects.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index cee9139..545d612 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,7 @@
"name": "frontend-next",
"version": "0.1.0",
"dependencies": {
+ "@storefront-ui/react": "^4.0.0",
"bcrypt": "^6.0.0",
"clsx": "^2.1.1",
"next": "^16.1.4",
@@ -42,9 +43,9 @@
}
},
"node_modules/@babel/code-frame": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz",
- "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==",
+ "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": {
@@ -98,14 +99,14 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz",
- "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==",
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.0.tgz",
+ "integrity": "sha512-vSH118/wwM/pLR38g/Sgk05sNtro6TlTJKuiMXDaZqPUfjTFcudpCOt00IhOfj+1BFAX+UFAlzCU+6WXr3GLFQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.28.6",
- "@babel/types": "^7.28.6",
+ "@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"
@@ -218,13 +219,13 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz",
- "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==",
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz",
+ "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.28.6"
+ "@babel/types": "^7.29.0"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -233,6 +234,15 @@
"node": ">=6.0.0"
}
},
+ "node_modules/@babel/runtime": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
+ "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/template": {
"version": "7.28.6",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
@@ -268,9 +278,9 @@
}
},
"node_modules/@babel/types": {
- "version": "7.28.6",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz",
- "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==",
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
+ "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
"devOptional": true,
"license": "MIT",
"dependencies": {
@@ -458,6 +468,31 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
+ "node_modules/@floating-ui/core": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.4.tgz",
+ "integrity": "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.10"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.7.5",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.5.tgz",
+ "integrity": "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/core": "^1.7.4",
+ "@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/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -1012,7 +1047,6 @@
"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": {
@@ -1238,6 +1272,131 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@storefront-ui/react": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/@storefront-ui/react/-/react-4.0.0.tgz",
+ "integrity": "sha512-yj3dKvxGJH4IkT+oh0+Q1WIcOBVhFuYMHFz6eLjJo/+hMRJVROkSe/lmaKo35iXQ4p8/DuIIkC2ZhM4VCLbF1w==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.0.9",
+ "@storefront-ui/shared": "3.1.0",
+ "@storefront-ui/tailwind-config": "3.1.0",
+ "classnames": "^2.5.1",
+ "jw-paginate": "^1.0.4",
+ "react-polymorphed": "^2.1.0",
+ "react-transition-group": "^4.4.5",
+ "react-use": "^17.5.1",
+ "tabbable": "^6.1.1",
+ "tailwind-merge": "^3.3.1"
+ },
+ "peerDependencies": {
+ "react": "^19.0.0"
+ }
+ },
+ "node_modules/@storefront-ui/react/node_modules/@floating-ui/react-dom": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.7.tgz",
+ "integrity": "sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/dom": "^1.7.5"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@storefront-ui/react/node_modules/react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0",
+ "react-dom": ">=16.6.0"
+ }
+ },
+ "node_modules/@storefront-ui/react/node_modules/react-use": {
+ "version": "17.6.0",
+ "resolved": "https://registry.npmjs.org/react-use/-/react-use-17.6.0.tgz",
+ "integrity": "sha512-OmedEScUMKFfzn1Ir8dBxiLLSOzhKe/dPZwVxcujweSj45aNM7BEGPb9BEVIgVEqEXx6f3/TsXzwIktNgUR02g==",
+ "license": "Unlicense",
+ "dependencies": {
+ "@types/js-cookie": "^2.2.6",
+ "@xobotyi/scrollbar-width": "^1.9.5",
+ "copy-to-clipboard": "^3.3.1",
+ "fast-deep-equal": "^3.1.3",
+ "fast-shallow-equal": "^1.0.0",
+ "js-cookie": "^2.2.1",
+ "nano-css": "^5.6.2",
+ "react-universal-interface": "^0.6.2",
+ "resize-observer-polyfill": "^1.5.1",
+ "screenfull": "^5.1.0",
+ "set-harmonic-interval": "^1.0.1",
+ "throttle-debounce": "^3.0.1",
+ "ts-easing": "^0.2.0",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-dom": "*"
+ }
+ },
+ "node_modules/@storefront-ui/react/node_modules/react-use/node_modules/nano-css": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.6.2.tgz",
+ "integrity": "sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==",
+ "license": "Unlicense",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.4.15",
+ "css-tree": "^1.1.2",
+ "csstype": "^3.1.2",
+ "fastest-stable-stringify": "^2.0.2",
+ "inline-style-prefixer": "^7.0.1",
+ "rtl-css-js": "^1.16.1",
+ "stacktrace-js": "^2.0.2",
+ "stylis": "^4.3.0"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-dom": "*"
+ }
+ },
+ "node_modules/@storefront-ui/shared": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@storefront-ui/shared/-/shared-3.1.0.tgz",
+ "integrity": "sha512-TqYPguDt8EBit1ukAM35jxVnwNvmIYrsOddYk0qN3Ij9MNEgXNGYYXczJCU3Ct2UHbzY9VTfR/JKA06uBYJrmw==",
+ "license": "MIT"
+ },
+ "node_modules/@storefront-ui/tailwind-config": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@storefront-ui/tailwind-config/-/tailwind-config-3.1.0.tgz",
+ "integrity": "sha512-f2qeb7ii2gWfjlkBLhQ7H2jpntu3G7aoxixlTcIfL0b38cNZPPxCsk5y40bptQ42gkJh10/Ne0eoM5YpLDNM8Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@storefront-ui/tw-plugin-peer-next": "3.1.0",
+ "@tailwindcss/container-queries": "^0.1.1"
+ },
+ "peerDependencies": {
+ "@tailwindcss/typography": ">=0.5.19",
+ "tailwindcss": ">= 4.0.0-alpha.20 || >= 4.0.0-beta.1 || >= 4.0.0"
+ }
+ },
+ "node_modules/@storefront-ui/tw-plugin-peer-next": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@storefront-ui/tw-plugin-peer-next/-/tw-plugin-peer-next-3.1.0.tgz",
+ "integrity": "sha512-690GvYL97S9YSI6dqtNKfEo/n6dJJXT5iq196yJWT0FmDi9I3uGdcN5+F419V4jRmePsYDhptlZCaZ6HQjwlNQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "tailwindcss": ">= 4.0.0-alpha.20 || >= 4.0.0-beta.1 || >= 4.0.0"
+ }
+ },
"node_modules/@swc/helpers": {
"version": "0.5.15",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
@@ -1247,6 +1406,15 @@
"tslib": "^2.8.0"
}
},
+ "node_modules/@tailwindcss/container-queries": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/container-queries/-/container-queries-0.1.1.tgz",
+ "integrity": "sha512-p18dswChx6WnTSaJCSGx6lTmrGzNNvm2FtXmiO6AuA1V4U5REyoqwmT6kgAsIMdjo07QdAfYXHJ4hnMtfHzWgA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "tailwindcss": ">=3.2.0"
+ }
+ },
"node_modules/@tailwindcss/node": {
"version": "4.1.18",
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz",
@@ -1518,6 +1686,19 @@
"tailwindcss": "4.1.18"
}
},
+ "node_modules/@tailwindcss/typography": {
+ "version": "0.5.19",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.19.tgz",
+ "integrity": "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "postcss-selector-parser": "6.0.10"
+ },
+ "peerDependencies": {
+ "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1"
+ }
+ },
"node_modules/@tybys/wasm-util": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
@@ -1546,6 +1727,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/js-cookie": {
+ "version": "2.2.7",
+ "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz",
+ "integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==",
+ "license": "MIT"
+ },
"node_modules/@types/json-schema": {
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
@@ -1574,7 +1761,6 @@
"version": "19.2.10",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.10.tgz",
"integrity": "sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"csstype": "^3.2.2"
@@ -2128,6 +2314,12 @@
"win32"
]
},
+ "node_modules/@xobotyi/scrollbar-width": {
+ "version": "1.9.5",
+ "resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz",
+ "integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==",
+ "license": "MIT"
+ },
"node_modules/acorn": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
@@ -2609,6 +2801,12 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
+ "node_modules/classnames": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
+ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
+ "license": "MIT"
+ },
"node_modules/client-only": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
@@ -2658,6 +2856,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/copy-to-clipboard": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
+ "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==",
+ "license": "MIT",
+ "dependencies": {
+ "toggle-selection": "^1.0.6"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -2673,11 +2880,45 @@
"node": ">= 8"
}
},
+ "node_modules/css-in-js-utils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz",
+ "integrity": "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==",
+ "license": "MIT",
+ "dependencies": {
+ "hyphenate-style-name": "^1.0.3"
+ }
+ },
+ "node_modules/css-tree": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz",
+ "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==",
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.0.14",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "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==",
+ "license": "MIT",
+ "peer": true,
+ "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/damerau-levenshtein": {
@@ -2825,6 +3066,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -2868,6 +3119,15 @@
"node": ">=10.13.0"
}
},
+ "node_modules/error-stack-parser": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
+ "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
+ "license": "MIT",
+ "dependencies": {
+ "stackframe": "^1.3.4"
+ }
+ },
"node_modules/es-abstract": {
"version": "1.24.1",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz",
@@ -3496,7 +3756,6 @@
"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": {
@@ -3543,6 +3802,17 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/fast-shallow-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz",
+ "integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw=="
+ },
+ "node_modules/fastest-stable-stringify": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz",
+ "integrity": "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==",
+ "license": "MIT"
+ },
"node_modules/fastq": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
@@ -3938,6 +4208,12 @@
"hermes-estree": "0.25.1"
}
},
+ "node_modules/hyphenate-style-name": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz",
+ "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==",
+ "license": "BSD-3-Clause"
+ },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -3975,6 +4251,15 @@
"node": ">=0.8.19"
}
},
+ "node_modules/inline-style-prefixer": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-7.0.1.tgz",
+ "integrity": "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==",
+ "license": "MIT",
+ "dependencies": {
+ "css-in-js-utils": "^3.1.0"
+ }
+ },
"node_modules/internal-slot": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
@@ -4447,11 +4732,16 @@
"jiti": "lib/jiti-cli.mjs"
}
},
+ "node_modules/js-cookie": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
+ "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==",
+ "license": "MIT"
+ },
"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==",
- "dev": true,
"license": "MIT"
},
"node_modules/js-yaml": {
@@ -4530,6 +4820,12 @@
"node": ">=4.0"
}
},
+ "node_modules/jw-paginate": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/jw-paginate/-/jw-paginate-1.0.4.tgz",
+ "integrity": "sha512-W0bv782exgCoynUL/egbRpaYwf/r6T6e02H870H5u3hfSgEYrxgz5POwmFF5aApS6iPi6yhZ0VF8IbafNFsntA==",
+ "license": "MIT"
+ },
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -4862,7 +5158,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
- "dev": true,
"license": "MIT",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
@@ -4901,6 +5196,12 @@
"node": ">= 0.4"
}
},
+ "node_modules/mdn-data": {
+ "version": "2.0.14",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
+ "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==",
+ "license": "CC0-1.0"
+ },
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -5108,7 +5409,6 @@
"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"
@@ -5393,6 +5693,20 @@
"node": "^10 || ^12 || >=14"
}
},
+ "node_modules/postcss-selector-parser": {
+ "version": "6.0.10",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
+ "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -5407,7 +5721,6 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.4.0",
@@ -5471,9 +5784,26 @@
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "dev": true,
"license": "MIT"
},
+ "node_modules/react-polymorphed": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/react-polymorphed/-/react-polymorphed-2.2.2.tgz",
+ "integrity": "sha512-8pv0VvOHITcmGs+E/FNAuE+4IZpIaKEThCJsvmp+NC54Lq5YbjHtPX0Af6H6MazhEQ7WQyJBt6b6aY+7WUytJw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": ">=16.8"
+ }
+ },
+ "node_modules/react-universal-interface": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz",
+ "integrity": "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==",
+ "peerDependencies": {
+ "react": "*",
+ "tslib": "*"
+ }
+ },
"node_modules/reflect.getprototypeof": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
@@ -5518,6 +5848,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/resize-observer-polyfill": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+ "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==",
+ "license": "MIT"
+ },
"node_modules/resolve": {
"version": "1.22.11",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
@@ -5570,6 +5906,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/rtl-css-js": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz",
+ "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.1.2"
+ }
+ },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -5655,6 +6000,18 @@
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
"license": "MIT"
},
+ "node_modules/screenfull": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz",
+ "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
@@ -5699,6 +6056,15 @@
"node": ">= 0.4"
}
},
+ "node_modules/set-harmonic-interval": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz",
+ "integrity": "sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==",
+ "license": "Unlicense",
+ "engines": {
+ "node": ">=6.9"
+ }
+ },
"node_modules/set-proto": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
@@ -5871,6 +6237,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -5887,6 +6262,51 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/stack-generator": {
+ "version": "2.0.10",
+ "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz",
+ "integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==",
+ "license": "MIT",
+ "dependencies": {
+ "stackframe": "^1.3.4"
+ }
+ },
+ "node_modules/stackframe": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
+ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
+ "license": "MIT"
+ },
+ "node_modules/stacktrace-gps": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz",
+ "integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==",
+ "license": "MIT",
+ "dependencies": {
+ "source-map": "0.5.6",
+ "stackframe": "^1.3.4"
+ }
+ },
+ "node_modules/stacktrace-gps/node_modules/source-map": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+ "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stacktrace-js": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz",
+ "integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==",
+ "license": "MIT",
+ "dependencies": {
+ "error-stack-parser": "^2.0.6",
+ "stack-generator": "^2.0.5",
+ "stacktrace-gps": "^3.0.4"
+ }
+ },
"node_modules/stop-iteration-iterator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
@@ -6060,6 +6480,12 @@
}
}
},
+ "node_modules/stylis": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz",
+ "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==",
+ "license": "MIT"
+ },
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -6086,6 +6512,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/tabbable": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz",
+ "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==",
+ "license": "MIT"
+ },
"node_modules/tailwind-merge": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz",
@@ -6100,7 +6532,6 @@
"version": "4.1.18",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
"integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
- "dev": true,
"license": "MIT"
},
"node_modules/tapable": {
@@ -6117,6 +6548,15 @@
"url": "https://opencollective.com/webpack"
}
},
+ "node_modules/throttle-debounce": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz",
+ "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/tinyglobby": {
"version": "0.2.15",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
@@ -6178,6 +6618,12 @@
"node": ">=8.0"
}
},
+ "node_modules/toggle-selection": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
+ "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==",
+ "license": "MIT"
+ },
"node_modules/ts-api-utils": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz",
@@ -6191,6 +6637,12 @@
"typescript": ">=4.8.4"
}
},
+ "node_modules/ts-easing": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz",
+ "integrity": "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==",
+ "license": "Unlicense"
+ },
"node_modules/tsconfig-paths": {
"version": "3.15.0",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
@@ -6454,6 +6906,13 @@
"punycode": "^2.1.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",
+ "peer": true
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
diff --git a/package.json b/package.json
index 98850af..4d500a2 100644
--- a/package.json
+++ b/package.json
@@ -9,6 +9,7 @@
"lint": "eslint"
},
"dependencies": {
+ "@storefront-ui/react": "^4.0.0",
"bcrypt": "^6.0.0",
"clsx": "^2.1.1",
"next": "^16.1.4",
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..702c941
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/src/app/(auth-required)/home/page.tsx b/src/app/(auth-required)/home/page.tsx
index e6827cd..1e33f13 100644
--- a/src/app/(auth-required)/home/page.tsx
+++ b/src/app/(auth-required)/home/page.tsx
@@ -1,16 +1,29 @@
"use client"
-import {Button} from "@/components/Button/Button";
+import {SingleCard} from "@/components/SingleCard/SingleCard";
+import {Link} from "@/components/Link";
export default function Page() {
return (
-
-
{
- alert("WOW")
- }} className={""}>
- Hallo Welt Knopf
-
-
Tes23
-
Tes23
+
+
+
+
+ Gibt es ein Problem?
+
+
{
+ }} typeStyle={"primary"}>Problem melden
+
+
+
+
+
+ Du möchtest deine Tickets ansehen?
+
+
{
+ }} typeStyle={"primary"}>Zur Ticketansicht
+
+
+
)
diff --git a/src/app/(auth-required)/layout.tsx b/src/app/(auth-required)/layout.tsx
index ed4b313..e91c0bb 100644
--- a/src/app/(auth-required)/layout.tsx
+++ b/src/app/(auth-required)/layout.tsx
@@ -1,8 +1,9 @@
-import type { Metadata } from "next";
-import { Geist, Geist_Mono } from "next/font/google";
+import type {Metadata} from "next";
+import {Geist, Geist_Mono} from "next/font/google";
import "@/app/globals.css";
import React from "react";
import {Header} from "@/components/Header/Header";
+import {Footer} from "@/components/Footer";
const geistSans = Geist({
variable: "--font-geist-sans",
@@ -28,11 +29,15 @@ export default function RootLayout({
return (
+
- {children}
+
+ {children}
+
+
);
diff --git a/src/app/(auth-required)/new/ticket/page.tsx b/src/app/(auth-required)/new/ticket/page.tsx
new file mode 100644
index 0000000..f7dbe9e
--- /dev/null
+++ b/src/app/(auth-required)/new/ticket/page.tsx
@@ -0,0 +1,159 @@
+'use client'
+import { use, useEffect, useState, ChangeEvent } from 'react'
+import { SingleCard } from "@/components/SingleCard/SingleCard";
+import Form from "next/dist/client/form";
+import { Button } from "@/components/Button";
+import {getCategories, Ticket} from "@/components/Tickets";
+import {sendRequestwTokenClient} from "@/app/actions/auth";
+import {getUser} from "@/components/getUser";
+import {useRouter} from "next/navigation";
+
+export default function Page({
+ params,
+ }: {
+ params: Promise<{ slug: string }>
+}) {
+
+ const router = useRouter();
+ const StateMapping = ["Offen","Bearbeitet","Abgeschlossen"]
+ const PrioMapping = ["Niedrig","Mittel","Hoch","Notfall"]
+
+
+ // Initialer State leer, damit wir keine Fehler bei undefined haben
+ const [currentUser, setCurrentUser] = useState
()
+ const [currentTicket, setCurrentTicket] = useState({
+ category: undefined,
+ description: "",
+ priority: 1,
+ status: 1,
+ ticketID: 1,
+ ticketname: "",
+ username: ""
+
+ });
+ const [categories, setCategories] = useState(null);
+
+ const { slug } = use(params);
+ const ticketId: number = Number(slug);
+
+
+ useEffect(() => {
+ const runAsync = async () => {
+ const category = await getCategories() || null;
+ const user = await getUser() || "none"
+ setCategories(category)
+ setCurrentUser(user)
+ setCurrentTicket((prev) => {return {...(prev as Ticket), username: user}})
+ }
+ runAsync();
+ }, [ticketId]);
+
+ // Zentraler Change-Handler für alle Inputs
+ const handleChange = (e: ChangeEvent) => {
+ const { name, value } = e.target;
+
+ setCurrentTicket((prev) => {
+ if (!prev) return null;
+
+ return {
+ ...prev,
+ [name]: value
+ };
+ });
+ };
+
+ const formAction = (e: FormData) => {
+
+ // Wenn du die Daten aus dem e: FormData Objekt ziehen willst (wie bisher):
+ const ticket: Ticket = {
+ status: Number(e.get("status")),
+ priority: Number(e.get("priority")),
+ category: e.get("category")?.toString(),
+ ticketname: e.get("ticketname")?.toString() || "none",
+ description: e.get("description")?.toString() || "none",
+ username: currentUser || "none",
+ };
+ sendRequestwTokenClient(`/ticket/create`, "POST",JSON.stringify(ticket))
+ router.push("/tickets")
+ };
+
+ if (!currentUser) {
+ return Loading...
+ }
+
+ return (
+
+ )
+}
\ No newline at end of file
diff --git a/src/app/(auth-required)/tickets/[slug]/page.tsx b/src/app/(auth-required)/tickets/[slug]/page.tsx
new file mode 100644
index 0000000..b2efcf0
--- /dev/null
+++ b/src/app/(auth-required)/tickets/[slug]/page.tsx
@@ -0,0 +1,147 @@
+'use client'
+import { use, useEffect, useState, ChangeEvent } from 'react'
+import { SingleCard } from "@/components/SingleCard/SingleCard";
+import Form from "next/dist/client/form";
+import { Button } from "@/components/Button";
+import {DetailedTicket, getCategories, Ticket} from "@/components/Tickets";
+import { getTicket } from "@/components/Tickets/getTicket";
+import {sendRequestwTokenClient} from "@/app/actions/auth";
+
+export default function Page({
+ params,
+ }: {
+ params: Promise<{ slug: string }>
+}) {
+
+ const StateMapping = ["A","B","C"]
+ const PrioMapping = ["Niedrig","Mittel","Hoch","Notfall"]
+
+
+ // Initialer State leer, damit wir keine Fehler bei undefined haben
+ const [currentTicket, setCurrentTicket] = useState(null);
+ const [categories, setCategories] = useState(null);
+
+ const { slug } = use(params);
+ const ticketId: number = Number(slug);
+
+
+ useEffect(() => {
+ const runAsync = async () => {
+ const ticket = await getTicket(ticketId) || null;
+ const category = await getCategories() || null;
+ setCategories(category)
+ setCurrentTicket(ticket);
+ }
+ runAsync();
+ }, [ticketId]);
+
+ // Zentraler Change-Handler für alle Inputs
+ const handleChange = (e: ChangeEvent) => {
+ const { name, value } = e.target;
+ console.log("IS CHANGED", name);
+
+ setCurrentTicket((prev) => {
+ if (!prev) return null;
+
+ return {
+ ...prev,
+ [name]: value
+ };
+ });
+ };
+
+ const formAction = (e: FormData) => {
+ // Hier kannst du die Daten an den Server schicken
+ console.log("Form submitted with:", currentTicket);
+
+ // Wenn du die Daten aus dem e: FormData Objekt ziehen willst (wie bisher):
+ const ticket: Ticket = {
+ status: Number(e.get("status")),
+ priority: Number(e.get("priority")),
+ category: e.get("category")?.toString(),
+ ticketname: e.get("ticketname")?.toString() || "none",
+ description: e.get("description")?.toString() || "none",
+ username: currentTicket?.username || "none",
+ };
+ sendRequestwTokenClient(`/ticket/update/${ticketId}`, "POST",JSON.stringify(ticket))
+ alert("Gespeichert!");
+ };
+
+ if (!currentTicket) return Lade Ticket...
;
+ console.log(currentTicket);
+ return (
+
+
+
+
+
+ Ticketname
+
+
+
+ Status
+
+ {
+ StateMapping?.map((value, index) => {
+ return ({value} )
+ })
+ }
+
+
+
+ Kategorie
+
+ {categories && categories?.map((value, index) => {
+ return ({value} )
+ })}
+
+
+
+ Priorität
+
+ {
+ PrioMapping?.map((value, index) => {
+ return ({value} )
+ })
+ }
+
+
+
+
+ Beschreibung
+
+
+ Bearbeiten
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/app/(auth-required)/tickets/page.tsx b/src/app/(auth-required)/tickets/page.tsx
new file mode 100644
index 0000000..07ab414
--- /dev/null
+++ b/src/app/(auth-required)/tickets/page.tsx
@@ -0,0 +1,18 @@
+'use server'
+
+import React from "react";
+import {SingleCard} from "@/components/SingleCard/SingleCard";
+import {TicketTable} from "@/components/TicketTable";
+
+export default async function Page() {
+
+ return (
+ <>
+
+ Deine Tickets
+
+
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/src/app/(no-auth)/layout.tsx b/src/app/(no-auth)/layout.tsx
index 795c675..a007abd 100644
--- a/src/app/(no-auth)/layout.tsx
+++ b/src/app/(no-auth)/layout.tsx
@@ -2,6 +2,8 @@ import type {Metadata} from "next";
import {Geist, Geist_Mono} from "next/font/google";
import "@/app/globals.css";
import React from "react";
+import {Header} from "@/components/Header/Header";
+import {Footer} from "@/components/Footer";
const geistSans = Geist({
variable: "--font-geist-sans",
@@ -25,13 +27,17 @@ export default function RootLayout({
}>) {
return (
-
+
- OFFENES LAYOUT
- {children}
+
+
+
+ {children}
+
+
);
diff --git a/src/app/(no-auth)/login/page.tsx b/src/app/(no-auth)/login/page.tsx
index 90b2fd3..21b56ff 100644
--- a/src/app/(no-auth)/login/page.tsx
+++ b/src/app/(no-auth)/login/page.tsx
@@ -1,12 +1,7 @@
-'use client'
+'use server'
import {SignInForm} from "@/components/SignInForm/SignInForm";
-interface Submission {
- username: string;
- password: string;
-}
-
-export default function Page() {
+export default async function Page() {
return (
diff --git a/src/app/actions/auth.ts b/src/app/actions/auth.ts
index 42a5111..a9a4220 100644
--- a/src/app/actions/auth.ts
+++ b/src/app/actions/auth.ts
@@ -1,9 +1,8 @@
'use server'
import {FormState} from '@/components/FormState/definitions'
import {ResponseToken} from "@/app/actions/interfaces";
-import { cookies } from 'next/headers'
+import {cookies} from 'next/headers'
import 'server-only'
-import {encrypt} from "next/dist/server/app-render/encryption-utils";
import {redirect} from "next/dist/client/components/redirect";
export async function signup(state: FormState, formData: FormData) {
@@ -14,15 +13,15 @@ export async function signup(state: FormState, formData: FormData) {
if (!username || !password) {
return {
errors: {
- name: !username ? ["username not defined"]: undefined,
+ name: !username ? ["username not defined"] : undefined,
message: !password ? ["password not defined"] : undefined,
}
}
}
console.log("Sign up", username, password)
-
- const endpoint: string = process.env.RUST_BACKEND_API_ENDPOINT as string;
+
+ const endpoint: string = process.env.API_ENDPOINT as string;
// 3. Insert the user into the database or call an Auth Library's API
@@ -40,11 +39,11 @@ export async function signup(state: FormState, formData: FormData) {
if (!resp.ok) {
return {
errors: {
- message: !resp.ok ? "Sign in unsuccessful" : undefined,
+ message: "Sign in unsuccessful"
}
}
}
-
+
const response = await resp.json() as ResponseToken;
const expiresAt = new Date(Date.now() + 25 * 60 * 60 * 1000)
@@ -52,8 +51,15 @@ export async function signup(state: FormState, formData: FormData) {
const cookieStore = await cookies()
cookieStore.set('token', response.token, {
- httpOnly: true,
- secure: true,
+ /*httpOnly: true,
+ secure: true, */
+ expires: expiresAt,
+ sameSite: 'lax',
+ path: '/',
+ })
+ cookieStore.set('user', username, {
+ /*httpOnly: true,
+ secure: true, */
expires: expiresAt,
sameSite: 'lax',
path: '/',
@@ -62,9 +68,13 @@ export async function signup(state: FormState, formData: FormData) {
redirect("/home")
}
-export async function sendRequestwToken(url: string,method: string, body?: JSON){
+export async function sendRequestwToken(url: string, method: string, body?: string): Promise {
const cookieStore = await cookies();
const token = cookieStore.get("token")?.value
+ const backendURL = process.env.API_ENDPOINT as string;
+ const fullUrl = `${backendURL}${url.startsWith("/") ? url: `/${url}`}`;
+
+
if (!token) return null;
@@ -75,9 +85,13 @@ export async function sendRequestwToken(url: string,method: string, body?: JSON)
"Authorization": bearerToken,
}
- return await fetch(url, {
+ return await fetch(fullUrl, {
method,
headers,
- body: body ? JSON.stringify(body) : undefined,
+ body: body ? body : undefined,
})
+}
+
+export async function sendRequestwTokenClient(url: string, method: string, body?: string) {
+ await sendRequestwToken(url, method, body)
}
\ No newline at end of file
diff --git a/src/app/favicon.ico b/src/app/favicon.ico
index 718d6fe..3a7be39 100644
Binary files a/src/app/favicon.ico and b/src/app/favicon.ico differ
diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx
index d6ddd9a..97431af 100644
--- a/src/components/Button/Button.tsx
+++ b/src/components/Button/Button.tsx
@@ -1,19 +1,11 @@
"use client"
import React from "react";
-import {ClassNameValue, twMerge} from "tailwind-merge"
-import {clsx} from "clsx";
+import {CustomButtonProps} from "@/components/Button";
+import {cn} from "@/components/cn";
-interface CustomButtonProps extends React.HTMLProps {
- children?: React.ReactNode
- type?: "button" | "submit" | "reset"
- typeStyle?: "primary" | "secondary" | "tertiary"
-}
+export function Button({children, className, onClick, typeStyle = "primary", link, ...otherProps}: CustomButtonProps) {
-const cn = (...input: ClassNameValue[]) => twMerge(clsx(input));
-
-export function Button({children, className, onClick, typeStyle = "primary", ...otherProps}: CustomButtonProps) {
-
- let typStyleCss = () => {
+ const typStyleCss = () => {
switch (typeStyle) {
case "primary":
return cn("bg-primary", "border-primary", "hover:border-tertiary");
@@ -35,10 +27,11 @@ export function Button({children, className, onClick, typeStyle = "primary", ...
typStyleCss(),
"transition-all",
"border-2",
- "p-1",
+ "p-2 pr-8 pl-8",
"rounded",
"m-2",
"text-center",
+ "text-2xl",
className,
onClick && "hover:cursor-pointer",
)
diff --git a/src/components/Button/index.ts b/src/components/Button/index.ts
new file mode 100644
index 0000000..c6917ba
--- /dev/null
+++ b/src/components/Button/index.ts
@@ -0,0 +1,2 @@
+export * from './Button';
+export * from './interfaces';
\ No newline at end of file
diff --git a/src/components/Button/interfaces.ts b/src/components/Button/interfaces.ts
new file mode 100644
index 0000000..b05b1e3
--- /dev/null
+++ b/src/components/Button/interfaces.ts
@@ -0,0 +1,6 @@
+export interface CustomButtonProps extends React.HTMLProps {
+ children?: React.ReactNode
+ type?: "button" | "submit" | "reset"
+ typeStyle?: "primary" | "secondary" | "tertiary"
+ link?: string
+}
\ No newline at end of file
diff --git a/src/components/DAL/dal.ts b/src/components/DAL/dal.ts
index c1689e3..ee39454 100644
--- a/src/components/DAL/dal.ts
+++ b/src/components/DAL/dal.ts
@@ -2,7 +2,7 @@
import 'server-only'
-import { cookies } from 'next/headers'
+import {cookies} from 'next/headers'
import {cache} from "react";
import {sendRequestwToken} from "@/app/actions/auth";
import {TokenIsValid} from "@/app/actions/interfaces";
@@ -10,13 +10,13 @@ import {TokenIsValid} from "@/app/actions/interfaces";
export const verifySession = cache(async () => {
const cookie = (await cookies()).get('token')?.value
- const resp = await sendRequestwToken(`${process.env.API_ENDPOINT}/token/validate`,'GET')
+ const resp = await sendRequestwToken(`/token/validate`, 'GET')
if (!cookie || resp === null) {
- return { isAuth: false, token: cookie }
+ return {isAuth: false, token: cookie}
}
-
+ console.log("hello world")
const is_valid = (await (resp as Response).json()) as TokenIsValid
- return { isAuth: is_valid.is_valid, token: cookie }
+ return {isAuth: is_valid.is_valid, token: cookie}
})
\ No newline at end of file
diff --git a/src/components/Footer/Footer.tsx b/src/components/Footer/Footer.tsx
new file mode 100644
index 0000000..0423d04
--- /dev/null
+++ b/src/components/Footer/Footer.tsx
@@ -0,0 +1,25 @@
+'use server'
+import {Link} from "@/components/Link";
+
+export async function Footer() {
+ const date = new Date();
+ const year = date.getFullYear();
+
+ return (
+
+
+
+
+
Home
+
Kontakt
+
Datenschutzerklärung
+
+
+ © {year} Leander Mundkowsky
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/Footer/index.ts b/src/components/Footer/index.ts
new file mode 100644
index 0000000..db4e675
--- /dev/null
+++ b/src/components/Footer/index.ts
@@ -0,0 +1 @@
+export * from './Footer';
\ No newline at end of file
diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx
index 88f4557..34d66e6 100644
--- a/src/components/Header/Header.tsx
+++ b/src/components/Header/Header.tsx
@@ -1,15 +1,52 @@
+'use client'
import Logo from "@/components/svg/logo";
+import {Notification} from "@/components/Notification";
+import {Link} from "@/components/Link";
+import {LogoutButton} from "@/components/LogoutButton";
+import {useLoggedState} from "@/components/isLoggedIn";
+import {getUser} from "@/components/getUser";
+import {useEffect, useState} from "react";
export function Header() {
+ const [username, setUsername] = useState(undefined);
+
+ useEffect(() => {
+ const execAsync = async () => {
+ const user = await getUser();
+ setUsername(user);
+ }
+
+ execAsync();
+ }, [])
+
+
+ const loggedState = useLoggedState();
return (
-
-
-
+
+
+
+
+ Home
+ Tickets
+ Nutzer
-
+
+ {loggedState &&
+ (<>
+
+
+
+ >
+
+ )
+ }
+
)
diff --git a/src/components/Link/Link.tsx b/src/components/Link/Link.tsx
new file mode 100644
index 0000000..6ac0094
--- /dev/null
+++ b/src/components/Link/Link.tsx
@@ -0,0 +1,44 @@
+'use client'
+import React from "react";
+import {cn} from "@/components/cn";
+import {CustomLinkProps} from "@/components/Link/interfaces";
+import NextLink from "next/link";
+
+export function Link({children, className, typeStyle = "primary", href, ...otherProps}: CustomLinkProps) {
+
+ const typStyleCss = () => {
+ switch (typeStyle) {
+ case "primary":
+ return cn("bg-primary", "border-primary", "hover:border-tertiary");
+ case "secondary":
+ return cn("bg-primary/75", "border-primary/70", "hover:border-secondary");
+ case "tertiary":
+ return cn("border-tertiary", "hover:bg-primary/50", "hover:border-primary");
+ default:
+ break;
+ }
+ }
+
+
+ return (
+
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/Link/index.ts b/src/components/Link/index.ts
new file mode 100644
index 0000000..eccf292
--- /dev/null
+++ b/src/components/Link/index.ts
@@ -0,0 +1,2 @@
+export * from './Link';
+export * from './interfaces';
\ No newline at end of file
diff --git a/src/components/Link/interfaces.ts b/src/components/Link/interfaces.ts
new file mode 100644
index 0000000..024f61b
--- /dev/null
+++ b/src/components/Link/interfaces.ts
@@ -0,0 +1,10 @@
+import {LinkProps} from "next/link";
+import React, {AnchorHTMLAttributes} from "react";
+import {Url} from "next/dist/shared/lib/router/router";
+
+export interface CustomLinkProps extends LinkProps, Omit
, keyof LinkProps> {
+ children?: React.ReactNode
+ type?: "button" | "submit" | "reset"
+ typeStyle?: "primary" | "secondary" | "tertiary"
+ link?: Url
+}
\ No newline at end of file
diff --git a/src/components/LogoutButton/LogoutButton.tsx b/src/components/LogoutButton/LogoutButton.tsx
new file mode 100644
index 0000000..e778d24
--- /dev/null
+++ b/src/components/LogoutButton/LogoutButton.tsx
@@ -0,0 +1,36 @@
+'use client'
+import {Button} from "@/components/Button";
+import {removeSession} from "@/components/LogoutButton/removeCookie";
+import {useEffect, useState} from "react";
+import Logout from "@/components/svg/logout";
+
+import {refresh} from "next/cache";
+
+export function LogoutButton() {
+
+ const [removeCookieState, setRemoveCookieState] = useState(false);
+
+ useEffect(() => {
+
+ if (!removeCookieState) {
+ return;
+ }
+ console.log("Cleared Login")
+
+ const execAsync = async () => {
+ await removeSession();
+ setRemoveCookieState(false);
+ }
+ execAsync();
+
+
+ }, [removeCookieState])
+
+ function onClick() {
+ setRemoveCookieState(true);
+ }
+
+ return (
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/LogoutButton/index.ts b/src/components/LogoutButton/index.ts
new file mode 100644
index 0000000..f317092
--- /dev/null
+++ b/src/components/LogoutButton/index.ts
@@ -0,0 +1 @@
+export * from "./LogoutButton"
\ No newline at end of file
diff --git a/src/components/LogoutButton/removeCookie.ts b/src/components/LogoutButton/removeCookie.ts
new file mode 100644
index 0000000..2cdb483
--- /dev/null
+++ b/src/components/LogoutButton/removeCookie.ts
@@ -0,0 +1,14 @@
+'use server'
+
+import {cookies} from "next/headers";
+import {redirect} from "next/dist/client/components/redirect";
+
+export async function removeSession() {
+
+ const cookieStore = await cookies()
+ cookieStore.delete("token")
+ cookieStore.delete("user")
+
+ redirect("/login")
+
+}
\ No newline at end of file
diff --git a/src/components/Notification/Notification.tsx b/src/components/Notification/Notification.tsx
new file mode 100644
index 0000000..e290ea8
--- /dev/null
+++ b/src/components/Notification/Notification.tsx
@@ -0,0 +1,38 @@
+'use client'
+
+import {Button} from "@/components/Button";
+import Bell from "@/components/svg/notifications/bell";
+import {useState} from "react";
+
+export function Notification() {
+ const [notificationIsActive, setNotificationIsActive] = useState(false);
+
+ return (
+ /* 'relative' sorgt dafür, dass das absolute Menü hier verankert bleibt */
+
+ setNotificationIsActive(!notificationIsActive)}
+ >
+
+
+
+ {notificationIsActive && }
+
+ );
+}
+
+function NotificationMenu() {
+ return (
+ /* 'absolute' nimmt das Element aus dem Fluss.
+ 'right-0' richtet es an der rechten Kante des Buttons aus.
+ 'z-50' sorgt dafür, dass es über dem Footer/Content liegt.
+ */
+
+
Benachrichtigungen
+
+
Hello World
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/Notification/index.ts b/src/components/Notification/index.ts
new file mode 100644
index 0000000..d9cc57f
--- /dev/null
+++ b/src/components/Notification/index.ts
@@ -0,0 +1 @@
+export * from './Notification';
\ No newline at end of file
diff --git a/src/components/Notification/interfaces.ts b/src/components/Notification/interfaces.ts
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/SignInForm/SignInForm.tsx b/src/components/SignInForm/SignInForm.tsx
index e47ced9..de29db9 100644
--- a/src/components/SignInForm/SignInForm.tsx
+++ b/src/components/SignInForm/SignInForm.tsx
@@ -1,18 +1,25 @@
+'use client'
import Form from "next/dist/client/form";
import {useActionState} from "react";
import {signup} from "@/app/actions/auth";
+import {Button} from "@/components/Button";
export function SignInForm() {
const [state, action, pending] = useActionState(signup, undefined)
return (
- <>
-
-
- {state?.errors?.name && {state.errors.name}
}
-
- Login
-
- >
-
+
+
+ {state?.errors?.name && {state.errors.name.map((item, i) => (
+
+ {item}
+
+ ))}}
+
+
+ Login
+
+
)
}
\ No newline at end of file
diff --git a/src/components/SingleCard/SingleCard.tsx b/src/components/SingleCard/SingleCard.tsx
new file mode 100644
index 0000000..3f6a2dc
--- /dev/null
+++ b/src/components/SingleCard/SingleCard.tsx
@@ -0,0 +1,17 @@
+'use client'
+import React from "react";
+import {cn} from "@/components/cn";
+
+interface SingleCardProps extends React.HTMLProps {
+ children?: React.ReactNode
+}
+
+export function SingleCard({children, className, ...props}: SingleCardProps) {
+
+ return (
+
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/SingleCard/index.ts b/src/components/SingleCard/index.ts
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/TicketTable/Row.tsx b/src/components/TicketTable/Row.tsx
new file mode 100644
index 0000000..b27dc19
--- /dev/null
+++ b/src/components/TicketTable/Row.tsx
@@ -0,0 +1,33 @@
+'use client'
+
+import {Ticket} from "@/components/Tickets";
+import {useRouter} from "next/navigation";
+import React from "react";
+
+export function Row({
+ ticketID,
+ ticketname,
+ username,
+ status,
+ priority,
+ category
+ }: Ticket) {
+ const router = useRouter()
+ const handleTableClick = () => {
+ router.push(`/tickets/${ticketID}`, {})
+ };
+ const StateMapping = ["Offen","Bearbeitet","Abgeschlossen"]
+ const PrioMapping = ["Niedrig","Mittel","Hoch","Notfall"]
+ return (
+
+ {ticketname}
+ {`${StateMapping[status]}`}
+ {`${PrioMapping[priority]}`}
+ {category}
+ {username}
+
+ )
+}
diff --git a/src/components/TicketTable/TicketTable.tsx b/src/components/TicketTable/TicketTable.tsx
new file mode 100644
index 0000000..f182b9e
--- /dev/null
+++ b/src/components/TicketTable/TicketTable.tsx
@@ -0,0 +1,72 @@
+import React from "react";
+import {Row} from "@/components/TicketTable";
+import {Ticket} from "@/components/Tickets";
+import {getTickets} from "@/components/Tickets/getTickets";
+
+
+export async function TicketTable() {
+
+ const tickets = await getTickets();
+ console.log(tickets);
+ const _mockData: Ticket[] = [{
+ "ticketID": 1,
+ "ticketname": "ADAQ",
+ "username": "admin",
+ "status": 1,
+ "priority": 5,
+ "category": "Crack",
+ "description": "string"
+ },
+ {
+ "ticketID": 2,
+ "ticketname": "ADAQ",
+ "username": "admin",
+ "status": 1,
+ "priority": 5,
+ "category": "Crack",
+ "description": "string"
+ },
+ {
+ "ticketID": 3,
+ "ticketname": "ADAQ",
+ "username": "admin",
+ "status": 1,
+ "priority": 5,
+ "category": "Crack",
+ "description": "string"
+ },
+ {
+ "ticketID": 4,
+ "ticketname": "ADAQ",
+ "username": "admin",
+ "status": 1,
+ "priority": 5,
+ "category": "Crack",
+ "description": "string"
+ }]
+
+
+ return (
+
+
+
+
+ Titel
+ Status
+ Priorität
+ Kategorie
+ Erstellt von
+
+
+
+ {tickets ? tickets.map((item, i) => (
+
+ )): (There are no Tickets available )}
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/TicketTable/index.ts b/src/components/TicketTable/index.ts
new file mode 100644
index 0000000..115dade
--- /dev/null
+++ b/src/components/TicketTable/index.ts
@@ -0,0 +1,2 @@
+export * from './TicketTable';
+export * from "./Row"
\ No newline at end of file
diff --git a/src/components/Tickets/getCategories.ts b/src/components/Tickets/getCategories.ts
new file mode 100644
index 0000000..cccf396
--- /dev/null
+++ b/src/components/Tickets/getCategories.ts
@@ -0,0 +1,18 @@
+'use server'
+import {sendRequestwToken} from "@/app/actions/auth";
+
+export async function getCategories() : Promise {
+
+ const result = await sendRequestwToken(`/categories`,"GET");
+
+ if (!(await result?.clone().text())) {
+ return undefined;
+ }
+ const ticket = (await result?.json()) as string[];
+
+ if (ticket === null || ticket === undefined) {
+ return undefined;
+ }
+
+ return ticket;
+}
\ No newline at end of file
diff --git a/src/components/Tickets/getTicket.ts b/src/components/Tickets/getTicket.ts
new file mode 100644
index 0000000..2dc0626
--- /dev/null
+++ b/src/components/Tickets/getTicket.ts
@@ -0,0 +1,19 @@
+'use server'
+import {sendRequestwToken} from "@/app/actions/auth";
+import {DetailedTicket} from "@/components/Tickets";
+
+export async function getTicket(ticketId: number) : Promise {
+
+ const result = await sendRequestwToken(`/ticket/show/${ticketId}`,"GET");
+
+ if (!(await result?.clone().text())) {
+ return undefined;
+ }
+ const ticket = (await result?.json()) as DetailedTicket;
+
+ if (ticket === null || ticket === undefined) {
+ return undefined;
+ }
+
+ return ticket;
+}
\ No newline at end of file
diff --git a/src/components/Tickets/getTickets.ts b/src/components/Tickets/getTickets.ts
new file mode 100644
index 0000000..1838308
--- /dev/null
+++ b/src/components/Tickets/getTickets.ts
@@ -0,0 +1,21 @@
+import {sendRequestwToken} from "@/app/actions/auth";
+import {Ticket} from "@/components/Tickets/interfaces";
+
+export async function getTickets() {
+
+ const result = await sendRequestwToken("/ticket/show/all","GET");
+ if (!(await result?.clone().text())) {
+ return undefined;
+ }
+ const tickets = await result?.json() as Ticket[];
+ console.log("/////////////////////////////")
+ console.dir(tickets);
+
+ console.log(tickets);
+
+ if (tickets === null || tickets === undefined) {
+ return undefined;
+ }
+
+ return tickets;
+}
\ No newline at end of file
diff --git a/src/components/Tickets/index.ts b/src/components/Tickets/index.ts
new file mode 100644
index 0000000..ed7a5f4
--- /dev/null
+++ b/src/components/Tickets/index.ts
@@ -0,0 +1,4 @@
+export * from "./interfaces"
+export * from "./getTicket"
+export * from "./getTickets"
+export * from "./getCategories"
\ No newline at end of file
diff --git a/src/components/Tickets/interfaces.ts b/src/components/Tickets/interfaces.ts
new file mode 100644
index 0000000..4f24b97
--- /dev/null
+++ b/src/components/Tickets/interfaces.ts
@@ -0,0 +1,23 @@
+export interface Ticket {
+ "ticketID"?: number,
+ "status" : number,
+ "priority": number,
+ "category": string | undefined,
+ "ticketname": string,
+ description?: string,
+ "username": string,
+}
+
+export interface Messages {
+ "messageID": number,
+ "sequence": number,
+ "sendAt": string,
+ "content": string,
+ "sender": number,
+ "senderUsername": string,
+}
+
+export interface DetailedTicket extends Ticket {
+ userID: number,
+ messages: Messages[] | undefined,
+}
\ No newline at end of file
diff --git a/src/components/UserTable/Row.tsx b/src/components/UserTable/Row.tsx
new file mode 100644
index 0000000..fd80f82
--- /dev/null
+++ b/src/components/UserTable/Row.tsx
@@ -0,0 +1,30 @@
+'use client'
+
+import {Ticket} from "@/components/Tickets";
+
+export function Row({
+ ticketID,
+ ticketname,
+ username,
+ status,
+ priority,
+ category
+ }: Ticket) {
+ const handleTableClick = (event: React.MouseEvent) => {
+ // Beispiel: ID aus einem Daten-Attribut auslesen
+ const target = event.currentTarget;
+ console.log("Zeile geklickt!");
+ };
+ return (
+
+ {ticketname}
+ {`${status}`}
+ {`${priority}`}
+ {category}
+ {username}
+
+ )
+}
diff --git a/src/components/UserTable/UserTable.tsx b/src/components/UserTable/UserTable.tsx
new file mode 100644
index 0000000..b7587b3
--- /dev/null
+++ b/src/components/UserTable/UserTable.tsx
@@ -0,0 +1,65 @@
+import React from "react";
+import {Row} from "@/components/TicketTable";
+import {RequestTicket} from "@/components/RequestTickets";
+
+
+export async function UserTable() {
+ const mockData: RequestTicket[] = [{
+ "ticketID": 1,
+ "ticketname": "ADAQ",
+ "username": "admin",
+ "status": 1,
+ "priority": 5,
+ "category": "Crack"
+ },
+ {
+ "ticketID": 2,
+ "ticketname": "ADAQ",
+ "username": "admin",
+ "status": 1,
+ "priority": 5,
+ "category": "Crack"
+ },
+ {
+ "ticketID": 3,
+ "ticketname": "ADAQ",
+ "username": "admin",
+ "status": 1,
+ "priority": 5,
+ "category": "Crack"
+ },
+ {
+ "ticketID": 4,
+ "ticketname": "ADAQ",
+ "username": "admin",
+ "status": 1,
+ "priority": 5,
+ "category": "Crack"
+ }]
+
+
+ return (
+
+ {/* Hinweis: mx-8 statt ml/mr für saubere Zentrierung bei w-full */}
+
+
+
+ Nutzer
+ Status
+ Priorität
+ Kategorie
+ Erstellt von
+
+
+
+ {mockData.map((item, i) => (
+
+ ))}
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/UserTable/index.ts b/src/components/UserTable/index.ts
new file mode 100644
index 0000000..112d9b4
--- /dev/null
+++ b/src/components/UserTable/index.ts
@@ -0,0 +1,2 @@
+export * from './UserTable';
+export * from "./Row"
\ No newline at end of file
diff --git a/src/components/cn/cn.tsx b/src/components/cn/cn.tsx
new file mode 100644
index 0000000..a5660f3
--- /dev/null
+++ b/src/components/cn/cn.tsx
@@ -0,0 +1,4 @@
+import {ClassNameValue, twMerge} from "tailwind-merge";
+import {clsx} from "clsx";
+
+export const cn = (...input: ClassNameValue[]) => twMerge(clsx(input));
\ No newline at end of file
diff --git a/src/components/cn/index.ts b/src/components/cn/index.ts
new file mode 100644
index 0000000..0c74e8e
--- /dev/null
+++ b/src/components/cn/index.ts
@@ -0,0 +1 @@
+export * from "./cn"
\ No newline at end of file
diff --git a/src/components/cn/interfaces.ts b/src/components/cn/interfaces.ts
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/getUser/getUser.ts b/src/components/getUser/getUser.ts
new file mode 100644
index 0000000..ea274f8
--- /dev/null
+++ b/src/components/getUser/getUser.ts
@@ -0,0 +1,7 @@
+'use server'
+import {cookies} from "next/headers";
+
+export async function getUser() {
+ const cookieStore = await cookies()
+ return cookieStore.get("user")?.value || undefined;
+}
\ No newline at end of file
diff --git a/src/components/getUser/index.ts b/src/components/getUser/index.ts
new file mode 100644
index 0000000..38ccb44
--- /dev/null
+++ b/src/components/getUser/index.ts
@@ -0,0 +1 @@
+export * from "./getUser"
\ No newline at end of file
diff --git a/src/components/isLoggedIn/index.ts b/src/components/isLoggedIn/index.ts
new file mode 100644
index 0000000..15f6280
--- /dev/null
+++ b/src/components/isLoggedIn/index.ts
@@ -0,0 +1,2 @@
+export * from "./isLoggedIn"
+export * from "./isLoggedInServer"
\ No newline at end of file
diff --git a/src/components/isLoggedIn/isLoggedIn.ts b/src/components/isLoggedIn/isLoggedIn.ts
new file mode 100644
index 0000000..57acfef
--- /dev/null
+++ b/src/components/isLoggedIn/isLoggedIn.ts
@@ -0,0 +1,26 @@
+'use client'
+
+import {useEffect, useState} from "react";
+import {usePathname} from "next/navigation";
+import {isLoggedInServer} from "@/components/isLoggedIn/isLoggedInServer";
+
+/**
+ * checks if the user is logged in
+ *
+ * Updates every time a new Path is evaluated
+ */
+export function useLoggedState() {
+ const [isLoggedinVal, setIsLoggedIn] = useState(false);
+
+ const path = usePathname()
+
+ useEffect(()=> {
+ const asyncReq = async () => {
+ const response = await isLoggedInServer()
+ setIsLoggedIn(response)
+ }
+ asyncReq()
+ },[path])
+
+ return isLoggedinVal
+}
diff --git a/src/components/isLoggedIn/isLoggedInServer.ts b/src/components/isLoggedIn/isLoggedInServer.ts
new file mode 100644
index 0000000..8e76a1e
--- /dev/null
+++ b/src/components/isLoggedIn/isLoggedInServer.ts
@@ -0,0 +1,11 @@
+'use server'
+import {cookies} from "next/headers";
+
+export async function isLoggedInServer() {
+ 'use server'
+ const cookieStore = await cookies()
+ const token = cookieStore.get('token');
+ const user = cookieStore.get("user");
+ return !!(user && token);
+
+}
\ No newline at end of file
diff --git a/src/components/svg/logo.tsx b/src/components/svg/logo.tsx
index 6bd48a7..c6031cf 100644
--- a/src/components/svg/logo.tsx
+++ b/src/components/svg/logo.tsx
@@ -1,17 +1,24 @@
import * as React from "react"
-import {SVGProps} from "react"
-
+import { SVGProps } from "react"
const Logo = (props: SVGProps) => (
-
-
-
+
+
+
)
-export default Logo
\ No newline at end of file
+export default Logo
diff --git a/src/components/svg/logout.tsx b/src/components/svg/logout.tsx
new file mode 100644
index 0000000..d5049d5
--- /dev/null
+++ b/src/components/svg/logout.tsx
@@ -0,0 +1,17 @@
+import * as React from "react"
+import {SVGProps} from "react"
+
+const Logout = (props: SVGProps) => (
+
+
+
+)
+export default Logout
diff --git a/src/components/svg/notifications/bell.tsx b/src/components/svg/notifications/bell.tsx
new file mode 100644
index 0000000..574b9c7
--- /dev/null
+++ b/src/components/svg/notifications/bell.tsx
@@ -0,0 +1,17 @@
+import * as React from "react"
+import {SVGProps} from "react"
+
+const Bell = (props: SVGProps) => (
+
+
+
+)
+export default Bell
diff --git a/src/components/svg/notifications/index.ts b/src/components/svg/notifications/index.ts
new file mode 100644
index 0000000..9afe012
--- /dev/null
+++ b/src/components/svg/notifications/index.ts
@@ -0,0 +1 @@
+export * from "./bell"
\ No newline at end of file
diff --git a/src/proxy.ts b/src/proxy.ts
index 3536468..3c427dc 100644
--- a/src/proxy.ts
+++ b/src/proxy.ts
@@ -1,8 +1,9 @@
import {NextRequest, NextResponse} from "next/server";
+import {verifySession} from "@/components/DAL/dal";
export default async function proxy(req: NextRequest) {
- const auth_is_valid = true // (await verifySession()).isAuth;
+ const auth_is_valid = (await verifySession()).isAuth;
const route_is_login = req.nextUrl.pathname === "/login"
if (route_is_login && auth_is_valid) { // Redirect User to Home if Login already acquired