enhance
@@ -3,6 +3,7 @@
|
||||
|
||||
# VCS
|
||||
.git
|
||||
.git_backup
|
||||
.gitignore
|
||||
|
||||
# Node / frontend
|
||||
@@ -12,6 +13,12 @@ frontend/dist
|
||||
frontend/.cache
|
||||
frontend/.next
|
||||
frontend/coverage
|
||||
app/node_modules
|
||||
app/build
|
||||
landing/node_modules
|
||||
landing/dist
|
||||
eshop/frontend/node_modules
|
||||
eshop/frontend/build
|
||||
|
||||
# Root-level node_modules if any
|
||||
node_modules
|
||||
|
||||
@@ -43,6 +43,7 @@ go.work
|
||||
# Frontend build files
|
||||
frontend/.next/
|
||||
frontend/out/
|
||||
frontend/build/
|
||||
|
||||
# Uploads directory
|
||||
/uploads/
|
||||
|
||||
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 27 KiB |
@@ -14,7 +14,7 @@
|
||||
"@react-navigation/bottom-tabs": "^6.6.1",
|
||||
"@react-navigation/native": "^6.1.18",
|
||||
"@react-navigation/native-stack": "^6.11.0",
|
||||
"axios": "^1.6.8",
|
||||
"axios": "^1.13.6",
|
||||
"expo": "~51.0.8",
|
||||
"expo-build-properties": "~0.12.5",
|
||||
"expo-camera": "~15.0.13",
|
||||
@@ -25,7 +25,7 @@
|
||||
"react": "18.2.0",
|
||||
"react-native": "0.74.5",
|
||||
"react-native-animated-pagination-dot": "^0.4.0",
|
||||
"react-native-device-info": "^15.0.1",
|
||||
"react-native-device-info": "^15.0.2",
|
||||
"react-native-gesture-handler": "~2.16.1",
|
||||
"react-native-haptic-feedback": "^2.3.3",
|
||||
"react-native-linear-gradient": "^2.8.3",
|
||||
@@ -36,18 +36,17 @@
|
||||
"react-native-svg": "15.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.24.7",
|
||||
"@babel/core": "^7.29.0",
|
||||
"@types/react": "~18.2.79",
|
||||
"@types/react-native": "0.73.0",
|
||||
"typescript": "~5.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
|
||||
"integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
|
||||
"integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.27.1",
|
||||
"@babel/helper-validator-identifier": "^7.28.5",
|
||||
"js-tokens": "^4.0.0",
|
||||
"picocolors": "^1.1.1"
|
||||
},
|
||||
@@ -56,27 +55,27 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/compat-data": {
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz",
|
||||
"integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==",
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
|
||||
"integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/core": {
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz",
|
||||
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
|
||||
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
"@babel/generator": "^7.28.5",
|
||||
"@babel/helper-compilation-targets": "^7.27.2",
|
||||
"@babel/helper-module-transforms": "^7.28.3",
|
||||
"@babel/helpers": "^7.28.4",
|
||||
"@babel/parser": "^7.28.5",
|
||||
"@babel/template": "^7.27.2",
|
||||
"@babel/traverse": "^7.28.5",
|
||||
"@babel/types": "^7.28.5",
|
||||
"@babel/code-frame": "^7.29.0",
|
||||
"@babel/generator": "^7.29.0",
|
||||
"@babel/helper-compilation-targets": "^7.28.6",
|
||||
"@babel/helper-module-transforms": "^7.28.6",
|
||||
"@babel/helpers": "^7.28.6",
|
||||
"@babel/parser": "^7.29.0",
|
||||
"@babel/template": "^7.28.6",
|
||||
"@babel/traverse": "^7.29.0",
|
||||
"@babel/types": "^7.29.0",
|
||||
"@jridgewell/remapping": "^2.3.5",
|
||||
"convert-source-map": "^2.0.0",
|
||||
"debug": "^4.1.0",
|
||||
@@ -93,12 +92,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/generator": {
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz",
|
||||
"integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==",
|
||||
"version": "7.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
|
||||
"integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.28.5",
|
||||
"@babel/types": "^7.28.5",
|
||||
"@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"
|
||||
@@ -119,11 +118,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-compilation-targets": {
|
||||
"version": "7.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
|
||||
"integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
|
||||
"version": "7.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
|
||||
"integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
|
||||
"dependencies": {
|
||||
"@babel/compat-data": "^7.27.2",
|
||||
"@babel/compat-data": "^7.28.6",
|
||||
"@babel/helper-validator-option": "^7.27.1",
|
||||
"browserslist": "^4.24.0",
|
||||
"lru-cache": "^5.1.1",
|
||||
@@ -216,25 +215,25 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-module-imports": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
|
||||
"integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
|
||||
"version": "7.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
|
||||
"integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
|
||||
"dependencies": {
|
||||
"@babel/traverse": "^7.27.1",
|
||||
"@babel/types": "^7.27.1"
|
||||
"@babel/traverse": "^7.28.6",
|
||||
"@babel/types": "^7.28.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-module-transforms": {
|
||||
"version": "7.28.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz",
|
||||
"integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==",
|
||||
"version": "7.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
|
||||
"integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
|
||||
"dependencies": {
|
||||
"@babel/helper-module-imports": "^7.27.1",
|
||||
"@babel/helper-validator-identifier": "^7.27.1",
|
||||
"@babel/traverse": "^7.28.3"
|
||||
"@babel/helper-module-imports": "^7.28.6",
|
||||
"@babel/helper-validator-identifier": "^7.28.5",
|
||||
"@babel/traverse": "^7.28.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -344,12 +343,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helpers": {
|
||||
"version": "7.28.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz",
|
||||
"integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==",
|
||||
"version": "7.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
|
||||
"integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
|
||||
"dependencies": {
|
||||
"@babel/template": "^7.27.2",
|
||||
"@babel/types": "^7.28.4"
|
||||
"@babel/template": "^7.28.6",
|
||||
"@babel/types": "^7.28.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -434,11 +433,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
|
||||
"integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz",
|
||||
"integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.28.5"
|
||||
"@babel/types": "^7.29.0"
|
||||
},
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
@@ -2008,29 +2007,29 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
|
||||
"integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
|
||||
"version": "7.28.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
|
||||
"integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
"@babel/parser": "^7.27.2",
|
||||
"@babel/types": "^7.27.1"
|
||||
"@babel/code-frame": "^7.28.6",
|
||||
"@babel/parser": "^7.28.6",
|
||||
"@babel/types": "^7.28.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/traverse": {
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz",
|
||||
"integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==",
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
|
||||
"integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
"@babel/generator": "^7.28.5",
|
||||
"@babel/code-frame": "^7.29.0",
|
||||
"@babel/generator": "^7.29.0",
|
||||
"@babel/helper-globals": "^7.28.0",
|
||||
"@babel/parser": "^7.28.5",
|
||||
"@babel/template": "^7.27.2",
|
||||
"@babel/types": "^7.28.5",
|
||||
"@babel/parser": "^7.29.0",
|
||||
"@babel/template": "^7.28.6",
|
||||
"@babel/types": "^7.29.0",
|
||||
"debug": "^4.3.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -2038,9 +2037,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
|
||||
"integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
|
||||
"integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.27.1",
|
||||
"@babel/helper-validator-identifier": "^7.28.5"
|
||||
@@ -4842,16 +4841,6 @@
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-native": {
|
||||
"version": "0.73.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.73.0.tgz",
|
||||
"integrity": "sha512-6ZRPQrYM72qYKGWidEttRe6M5DZBEV5F+MHMHqd4TTYx0tfkcdrUFGdef6CCxY0jXU7wldvd/zA/b0A/kTeJmA==",
|
||||
"deprecated": "This is a stub types definition. react-native provides its own type definitions, so you do not need this installed.",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/stack-utils": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
|
||||
@@ -5208,12 +5197,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
|
||||
"integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
|
||||
"version": "1.13.6",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz",
|
||||
"integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.4",
|
||||
"follow-redirects": "^1.15.11",
|
||||
"form-data": "^4.0.5",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
@@ -5573,12 +5562,23 @@
|
||||
"node": "^16.14.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cacache/node_modules/balanced-match": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
||||
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
|
||||
"engines": {
|
||||
"node": "18 || 20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/cacache/node_modules/brace-expansion": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz",
|
||||
"integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
"balanced-match": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "18 || 20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/cacache/node_modules/glob": {
|
||||
@@ -5606,11 +5606,11 @@
|
||||
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="
|
||||
},
|
||||
"node_modules/cacache/node_modules/minimatch": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||
"version": "9.0.7",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.7.tgz",
|
||||
"integrity": "sha512-MOwgjc8tfrpn5QQEvjijjmDVtMw2oL88ugTevzxQnzRLm6l3fVEF2gzU0kYeYYKD8C66+IdGX6peJ4MyUlUnPg==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
"brace-expansion": "^5.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
@@ -7163,9 +7163,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/fast-xml-parser": {
|
||||
"version": "4.5.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz",
|
||||
"integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==",
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.4.tgz",
|
||||
"integrity": "sha512-jE8ugADnYOBsu1uaoayVl1tVKAMNOXyjwvv2U6udEA2ORBhDooJDWoGxTkhd4Qn4yh59JVVt/pKXtjPwx9OguQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -7173,7 +7173,7 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"strnum": "^1.1.1"
|
||||
"strnum": "^1.0.5"
|
||||
},
|
||||
"bin": {
|
||||
"fxparser": "src/cli/cli.js"
|
||||
@@ -10136,9 +10136,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.3.tgz",
|
||||
"integrity": "sha512-M2GCs7Vk83NxkUyQV1bkABc4yxgz9kILhHImZiBPAZ9ybuvCb0/H7lEl5XvIg3g+9d4eNotkZA5IWwYl0tibaA==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
@@ -11573,9 +11573,9 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/react-native-device-info": {
|
||||
"version": "15.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-15.0.1.tgz",
|
||||
"integrity": "sha512-U5waZRXtT3l1SgZpZMlIvMKPTkFZPH8W7Ks6GrJhdH723aUIPxjVer7cRSij1mvQdOAAYFJV/9BDzlC8apG89A==",
|
||||
"version": "15.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-15.0.2.tgz",
|
||||
"integrity": "sha512-dd71eXG2l3Cwp66IvKNadMTB8fhU3PEjyVddI97sYan+D4bgIAUmgGDhbSOFvHcGavksb2U17kiQYaDiK2WK2g==",
|
||||
"peerDependencies": {
|
||||
"react-native": "*"
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"@react-navigation/bottom-tabs": "^6.6.1",
|
||||
"@react-navigation/native": "^6.1.18",
|
||||
"@react-navigation/native-stack": "^6.11.0",
|
||||
"axios": "^1.6.8",
|
||||
"axios": "^1.13.6",
|
||||
"expo": "~51.0.8",
|
||||
"expo-build-properties": "~0.12.5",
|
||||
"expo-camera": "~15.0.13",
|
||||
@@ -28,7 +28,7 @@
|
||||
"react": "18.2.0",
|
||||
"react-native": "0.74.5",
|
||||
"react-native-animated-pagination-dot": "^0.4.0",
|
||||
"react-native-device-info": "^15.0.1",
|
||||
"react-native-device-info": "^15.0.2",
|
||||
"react-native-gesture-handler": "~2.16.1",
|
||||
"react-native-haptic-feedback": "^2.3.3",
|
||||
"react-native-linear-gradient": "^2.8.3",
|
||||
@@ -39,9 +39,17 @@
|
||||
"react-native-svg": "15.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.24.7",
|
||||
"@babel/core": "^7.29.0",
|
||||
"@types/react": "~18.2.79",
|
||||
"@types/react-native": "0.73.0",
|
||||
"typescript": "~5.3.3"
|
||||
},
|
||||
"overrides": {
|
||||
"fast-xml-parser": "4.5.4",
|
||||
"glob@10": {
|
||||
"minimatch": "9.0.7"
|
||||
},
|
||||
"glob@7": {
|
||||
"minimatch": "3.1.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import { isFanLogged, isAdminLogged } from './services/auth';
|
||||
|
||||
const AppContent = () => {
|
||||
const { pinnedClub, isClubReady } = useClub();
|
||||
const { themeReady, theme } = useClubTheme(pinnedClub);
|
||||
const { themeReady, theme } = useClubTheme(pinnedClub ?? undefined);
|
||||
|
||||
useEffect(() => {
|
||||
// Initialize push notifications when club is ready
|
||||
|
||||
@@ -175,7 +175,7 @@ export const ModernInput: React.FC<ModernInputProps> = ({
|
||||
{label && <Text style={{ fontSize: 14, fontWeight: '600', marginBottom: 8, color: '#374151' }}>{label}</Text>}
|
||||
<View style={[
|
||||
{ flexDirection: 'row', alignItems: 'center', borderWidth: 1, borderRadius: 12, paddingHorizontal: 16, paddingVertical: 12, backgroundColor: '#FFFFFF' },
|
||||
error && { borderWidth: 2, borderColor: '#EF4444' },
|
||||
Boolean(error) && { borderWidth: 2, borderColor: '#EF4444' },
|
||||
!error && { borderColor: theme.primary + '30' }
|
||||
]}>
|
||||
{icon && <Text style={{ marginRight: 12, fontSize: 16 }}>{icon}</Text>}
|
||||
|
||||
@@ -36,14 +36,14 @@ const TicketScreen: React.FC = () => {
|
||||
|
||||
return (
|
||||
<ScrollView contentContainerStyle={styles.container}>
|
||||
<Text style={styles.title}>{ticket.campaignTitle}</Text>
|
||||
<Text style={styles.title}>{ticket.event}</Text>
|
||||
<Text style={styles.sub}>QR průkaz pro vstup</Text>
|
||||
<View style={styles.qrBox}>
|
||||
<QRCode value={JSON.stringify(ticket)} size={240} backgroundColor="#fff" color="#000" />
|
||||
</View>
|
||||
<Text style={styles.code}>Kód: {ticket.barcode}</Text>
|
||||
<Text style={styles.info}>Držitel: {ticket.holderName}</Text>
|
||||
{ticket.matchDateTime && <Text style={styles.info}>Datum: {ticket.matchDateTime}</Text>}
|
||||
<Text style={styles.info}>Držitel: {ticket.holder}</Text>
|
||||
{ticket.date && <Text style={styles.info}>Datum: {ticket.date}</Text>}
|
||||
{ticket.venue && <Text style={styles.info}>Místo: {ticket.venue}</Text>}
|
||||
<TouchableOpacity style={styles.button} onPress={() => { /* TODO: add Wallet pass later */ }}>
|
||||
<Text style={styles.buttonText}>Uložit / sdílet</Text>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
|
||||
import axios, { AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
|
||||
import Constants from 'expo-constants';
|
||||
import * as Linking from 'expo-linking';
|
||||
|
||||
@@ -50,7 +50,7 @@ export async function getApi(): Promise<AxiosInstance> {
|
||||
timeout: 15000,
|
||||
});
|
||||
|
||||
apiInstance.interceptors.request.use((config: AxiosRequestConfig) => config);
|
||||
apiInstance.interceptors.request.use((config: InternalAxiosRequestConfig) => config);
|
||||
apiInstance.interceptors.response.use(
|
||||
(resp: AxiosResponse) => resp,
|
||||
(err) => Promise.reject(err)
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"etag":"","fetched_at":"2026-03-13T16:17:10Z","last_modified":""}
|
||||
{"etag":"","fetched_at":"2026-03-13T17:47:16Z","last_modified":""}
|
||||
@@ -1 +1 @@
|
||||
{"etag":"","fetched_at":"2026-03-13T16:17:10Z","last_modified":""}
|
||||
{"etag":"","fetched_at":"2026-03-13T17:47:16Z","last_modified":""}
|
||||
@@ -1 +1 @@
|
||||
{"etag":"","fetched_at":"2026-03-13T16:17:10Z","last_modified":""}
|
||||
{"etag":"","fetched_at":"2026-03-13T17:47:16Z","last_modified":""}
|
||||
@@ -1 +1 @@
|
||||
{"lastUpdated":"2026-03-13T16:17:10Z"}
|
||||
{"lastUpdated":"2026-03-13T17:47:16Z"}
|
||||
@@ -1,22 +1,7 @@
|
||||
{
|
||||
"baseURL": "http://localhost:8080/api/v1",
|
||||
"duration_ms": 94,
|
||||
"duration_ms": 29,
|
||||
"endpoints": [
|
||||
{
|
||||
"path": "/articles?page=1\u0026page_size=10\u0026published=true",
|
||||
"file": "articles.json",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"path": "/sponsors",
|
||||
"file": "sponsors.json",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"path": "/events/upcoming",
|
||||
"file": "events_upcoming.json",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"path": "/public/team-logo-overrides",
|
||||
"file": "team_logo_overrides.json",
|
||||
@@ -36,7 +21,22 @@
|
||||
"path": "/seo",
|
||||
"file": "seo.json",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"path": "/articles?page=1\u0026page_size=10\u0026published=true",
|
||||
"file": "articles.json",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"path": "/sponsors",
|
||||
"file": "sponsors.json",
|
||||
"ok": true
|
||||
},
|
||||
{
|
||||
"path": "/events/upcoming",
|
||||
"file": "events_upcoming.json",
|
||||
"ok": true
|
||||
}
|
||||
],
|
||||
"lastUpdated": "2026-03-13T16:17:10Z"
|
||||
"lastUpdated": "2026-03-13T17:47:16Z"
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
{"etag":"","fetched_at":"2026-03-13T16:17:10Z","last_modified":""}
|
||||
{"etag":"","fetched_at":"2026-03-13T17:47:16Z","last_modified":""}
|
||||
@@ -1 +1 @@
|
||||
{"etag":"","fetched_at":"2026-03-13T16:17:10Z","last_modified":""}
|
||||
{"etag":"","fetched_at":"2026-03-13T17:47:16Z","last_modified":""}
|
||||
@@ -1 +1 @@
|
||||
{"etag":"","fetched_at":"2026-03-13T16:17:10Z","last_modified":""}
|
||||
{"etag":"","fetched_at":"2026-03-13T17:47:16Z","last_modified":""}
|
||||
@@ -1 +1 @@
|
||||
{"etag":"","fetched_at":"2026-03-13T16:17:10Z","last_modified":""}
|
||||
{"etag":"","fetched_at":"2026-03-13T17:47:16Z","last_modified":""}
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"fetched_at": "2026-03-13T16:17:09Z",
|
||||
"fetched_at": "2026-03-13T17:47:16Z",
|
||||
"link": ""
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"files": {
|
||||
"main.js": "/static/js/main.590e0c36.js",
|
||||
"index.html": "/index.html",
|
||||
"main.590e0c36.js.map": "/static/js/main.590e0c36.js.map"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/js/main.590e0c36.js"
|
||||
]
|
||||
}
|
||||
@@ -1 +1,14 @@
|
||||
<!doctype html><html lang="cs"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#1a365d"/><title>MyClub E-shop</title><script defer="defer" src="/static/js/main.590e0c36.js"></script></head><body><noscript>Pro zobrazení e-shopu je potřeba povolit JavaScript.</noscript><div id="root"></div></body></html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="cs">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#1a365d" />
|
||||
<title>MyClub E-shop</title>
|
||||
<script type="module" crossorigin src="/static/index-D1MwVPqi.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>Pro zobrazení e-shopu je potřeba povolit JavaScript.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* use-sync-external-store-shim.production.js
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @remix-run/router v1.23.1
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE.md file in the root directory of this source tree.
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/**
|
||||
* React Router DOM v6.30.2
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE.md file in the root directory of this source tree.
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/**
|
||||
* React Router v6.30.2
|
||||
*
|
||||
* Copyright (c) Remix Software Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE.md file in the root directory of this source tree.
|
||||
*
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/** @license React v16.13.1
|
||||
* react-is.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
@@ -11,21 +11,20 @@
|
||||
"@chakra-ui/react": "^2.8.2",
|
||||
"@emotion/react": "^11.11.1",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@stripe/react-stripe-js": "^5.4.1",
|
||||
"@stripe/stripe-js": "^8.5.3",
|
||||
"@tanstack/react-query": "^4.36.1",
|
||||
"@stripe/react-stripe-js": "^5.6.1",
|
||||
"@stripe/stripe-js": "^8.9.0",
|
||||
"@tanstack/react-query": "^4.43.0",
|
||||
"axios": "^1.13.6",
|
||||
"dompurify": "^3.3.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-router-dom": "^6.30.2",
|
||||
"react-icons": "^5.6.0",
|
||||
"react-router-dom": "^6.30.3",
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.45",
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"@vitejs/plugin-react": "^4.4.1",
|
||||
"jsdom": "^26.1.0",
|
||||
"vite": "^6.3.5",
|
||||
@@ -1148,9 +1147,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/router": {
|
||||
"version": "1.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.1.tgz",
|
||||
"integrity": "sha512-vDbaOzF7yT2Qs4vO6XV1MHcJv+3dgR1sT+l3B8xxOVhUC336prMvqrvsLL/9Dnw2xr6Qhz4J0dmS0llNAbnUmQ==",
|
||||
"version": "1.23.2",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.2.tgz",
|
||||
"integrity": "sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
@@ -1487,9 +1486,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@stripe/react-stripe-js": {
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-5.4.1.tgz",
|
||||
"integrity": "sha512-ipeYcAHa4EPmjwfv0lFE+YDVkOQ0TMKkFWamW+BqmnSkEln/hO8rmxGPPWcd9WjqABx6Ro8Xg4pAS7evCcR9cw==",
|
||||
"version": "5.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-5.6.1.tgz",
|
||||
"integrity": "sha512-5xBrjkGmFvKvpMod6VvpOaFaa67eRbmieKeFTePZyOr/sUXzm7A3YY91l330pS0usUst5PxTZDUZHWfOc0v1GA==",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.7.2"
|
||||
},
|
||||
@@ -1500,29 +1499,29 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stripe/stripe-js": {
|
||||
"version": "8.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-8.5.3.tgz",
|
||||
"integrity": "sha512-UM0GHAxlTN7v0lCK2P6t0VOlvBIdApIQxhnM3yZ2kupQ4PpSrLsK/n/NyYKtw2NJGMaNRRD1IicWS7fSL2sFtA==",
|
||||
"version": "8.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-8.9.0.tgz",
|
||||
"integrity": "sha512-OJkXvUI5GAc56QdiSRimQDvWYEqn475J+oj8RzRtFTCPtkJNO2TWW619oDY+nn1ExR+2tCVTQuRQBbR4dRugww==",
|
||||
"engines": {
|
||||
"node": ">=12.16"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/query-core": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.41.0.tgz",
|
||||
"integrity": "sha512-193R4Jp9hjvlij6LryxrB5Mpbffd2L9PeWh3KlIy/hJV4SkBOfiQZ+jc5qAZLDCrdbkA5FjGj+UoDYw6TcNnyA==",
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.43.0.tgz",
|
||||
"integrity": "sha512-m1QeUUIpNXDYxmfuuWNFZLky0EwVmbE0hj8ulZ2nIGA1183raJgDCn0IKlxug80NotRqzodxAaoYTKHbE1/P/Q==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/react-query": {
|
||||
"version": "4.42.0",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.42.0.tgz",
|
||||
"integrity": "sha512-j0tiofkzE3CSrYKmVRaKuwGgvCE+P2OOEDlhmfjeZf5ufcuFHwYwwgw3j08n4WYPVZ+OpsHblcFYezhKA3jDwg==",
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.43.0.tgz",
|
||||
"integrity": "sha512-Lj8luFKHQL27oZbw5T8xdTbsfAPp2+bCtSCa2bAVvIwnvNfRP0hpB1GxfKFgCktat8lPcYBHAu8eMTXzz2sQtQ==",
|
||||
"dependencies": {
|
||||
"@tanstack/query-core": "4.41.0",
|
||||
"use-sync-external-store": "^1.2.0"
|
||||
"@tanstack/query-core": "4.43.0",
|
||||
"use-sync-external-store": "^1.6.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
@@ -1605,12 +1604,6 @@
|
||||
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/history": {
|
||||
"version": "4.7.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz",
|
||||
"integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.21.tgz",
|
||||
@@ -1665,27 +1658,6 @@
|
||||
"@types/react": "^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-router": {
|
||||
"version": "5.1.20",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz",
|
||||
"integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/history": "^4.7.11",
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-router-dom": {
|
||||
"version": "5.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz",
|
||||
"integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/history": "^4.7.11",
|
||||
"@types/react": "*",
|
||||
"@types/react-router": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/trusted-types": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
||||
@@ -3061,9 +3033,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-icons": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
|
||||
"integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==",
|
||||
"version": "5.6.0",
|
||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.6.0.tgz",
|
||||
"integrity": "sha512-RH93p5ki6LfOiIt0UtDyNg/cee+HLVR6cHHtW3wALfo+eOHTp8RnU2kRkI6E+H19zMIs03DyxUG/GfZMOGvmiA==",
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
}
|
||||
@@ -3119,11 +3091,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-router": {
|
||||
"version": "6.30.2",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.2.tgz",
|
||||
"integrity": "sha512-H2Bm38Zu1bm8KUE5NVWRMzuIyAV8p/JrOaBJAwVmp37AXG72+CZJlEBw6pdn9i5TBgLMhNDgijS4ZlblpHyWTA==",
|
||||
"version": "6.30.3",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.3.tgz",
|
||||
"integrity": "sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==",
|
||||
"dependencies": {
|
||||
"@remix-run/router": "1.23.1"
|
||||
"@remix-run/router": "1.23.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
@@ -3133,12 +3105,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-router-dom": {
|
||||
"version": "6.30.2",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.2.tgz",
|
||||
"integrity": "sha512-l2OwHn3UUnEVUqc6/1VMmR1cvZryZ3j3NzapC2eUXO1dB0sYp5mvwdjiXhpUbRb21eFow3qSxpP8Yv6oAU824Q==",
|
||||
"version": "6.30.3",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.3.tgz",
|
||||
"integrity": "sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==",
|
||||
"dependencies": {
|
||||
"@remix-run/router": "1.23.1",
|
||||
"react-router": "6.30.2"
|
||||
"@remix-run/router": "1.23.2",
|
||||
"react-router": "6.30.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
|
||||
@@ -13,21 +13,20 @@
|
||||
"@chakra-ui/react": "^2.8.2",
|
||||
"@emotion/react": "^11.11.1",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@stripe/react-stripe-js": "^5.4.1",
|
||||
"@stripe/stripe-js": "^8.5.3",
|
||||
"@tanstack/react-query": "^4.36.1",
|
||||
"@stripe/react-stripe-js": "^5.6.1",
|
||||
"@stripe/stripe-js": "^8.9.0",
|
||||
"@tanstack/react-query": "^4.43.0",
|
||||
"axios": "^1.13.6",
|
||||
"dompurify": "^3.3.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-router-dom": "^6.30.2",
|
||||
"react-icons": "^5.6.0",
|
||||
"react-router-dom": "^6.30.3",
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.45",
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"@vitejs/plugin-react": "^4.4.1",
|
||||
"jsdom": "^26.1.0",
|
||||
"vite": "^6.3.5",
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "/static/css/main.e9950038.css",
|
||||
"main.js": "/static/js/main.dd323bc8.js",
|
||||
"runtime.js": "/static/js/runtime.0b5f0839.js",
|
||||
"static/js/469.ec731235.chunk.js": "/static/js/469.ec731235.chunk.js",
|
||||
"static/js/910.bec7c150.chunk.js": "/static/js/910.bec7c150.chunk.js",
|
||||
"static/js/154.a93817c6.chunk.js": "/static/js/154.a93817c6.chunk.js",
|
||||
"static/js/771.2b2378c2.chunk.js": "/static/js/771.2b2378c2.chunk.js",
|
||||
"static/js/558.0464ebe3.chunk.js": "/static/js/558.0464ebe3.chunk.js",
|
||||
"static/js/334.0d196877.chunk.js": "/static/js/334.0d196877.chunk.js",
|
||||
"static/js/118.8a550f36.chunk.js": "/static/js/118.8a550f36.chunk.js",
|
||||
"static/js/339.c1ec8d08.chunk.js": "/static/js/339.c1ec8d08.chunk.js",
|
||||
"static/js/158.c7e50479.chunk.js": "/static/js/158.c7e50479.chunk.js",
|
||||
"static/js/798.21001033.chunk.js": "/static/js/798.21001033.chunk.js",
|
||||
"static/js/620.edc51951.chunk.js": "/static/js/620.edc51951.chunk.js",
|
||||
"static/js/548.da462cb8.chunk.js": "/static/js/548.da462cb8.chunk.js",
|
||||
"static/js/501.0b99fbb0.chunk.js": "/static/js/501.0b99fbb0.chunk.js",
|
||||
"static/js/266.e18a46b8.chunk.js": "/static/js/266.e18a46b8.chunk.js",
|
||||
"static/js/452.bad3d00e.chunk.js": "/static/js/452.bad3d00e.chunk.js",
|
||||
"static/js/791.2cae987d.chunk.js": "/static/js/791.2cae987d.chunk.js",
|
||||
"static/js/579.f8a21d69.chunk.js": "/static/js/579.f8a21d69.chunk.js",
|
||||
"static/js/453.d9749a7d.chunk.js": "/static/js/453.d9749a7d.chunk.js",
|
||||
"static/css/664.02d4d120.css": "/static/css/664.02d4d120.css",
|
||||
"static/js/664.d9b6a63b.js": "/static/js/664.d9b6a63b.js",
|
||||
"index.html": "/index.html",
|
||||
"main.e9950038.css.map": "/static/css/main.e9950038.css.map",
|
||||
"main.dd323bc8.js.map": "/static/js/main.dd323bc8.js.map",
|
||||
"runtime.0b5f0839.js.map": "/static/js/runtime.0b5f0839.js.map",
|
||||
"469.ec731235.chunk.js.map": "/static/js/469.ec731235.chunk.js.map",
|
||||
"910.bec7c150.chunk.js.map": "/static/js/910.bec7c150.chunk.js.map",
|
||||
"154.a93817c6.chunk.js.map": "/static/js/154.a93817c6.chunk.js.map",
|
||||
"771.2b2378c2.chunk.js.map": "/static/js/771.2b2378c2.chunk.js.map",
|
||||
"558.0464ebe3.chunk.js.map": "/static/js/558.0464ebe3.chunk.js.map",
|
||||
"334.0d196877.chunk.js.map": "/static/js/334.0d196877.chunk.js.map",
|
||||
"118.8a550f36.chunk.js.map": "/static/js/118.8a550f36.chunk.js.map",
|
||||
"339.c1ec8d08.chunk.js.map": "/static/js/339.c1ec8d08.chunk.js.map",
|
||||
"158.c7e50479.chunk.js.map": "/static/js/158.c7e50479.chunk.js.map",
|
||||
"798.21001033.chunk.js.map": "/static/js/798.21001033.chunk.js.map",
|
||||
"620.edc51951.chunk.js.map": "/static/js/620.edc51951.chunk.js.map",
|
||||
"548.da462cb8.chunk.js.map": "/static/js/548.da462cb8.chunk.js.map",
|
||||
"501.0b99fbb0.chunk.js.map": "/static/js/501.0b99fbb0.chunk.js.map",
|
||||
"266.e18a46b8.chunk.js.map": "/static/js/266.e18a46b8.chunk.js.map",
|
||||
"452.bad3d00e.chunk.js.map": "/static/js/452.bad3d00e.chunk.js.map",
|
||||
"791.2cae987d.chunk.js.map": "/static/js/791.2cae987d.chunk.js.map",
|
||||
"579.f8a21d69.chunk.js.map": "/static/js/579.f8a21d69.chunk.js.map",
|
||||
"453.d9749a7d.chunk.js.map": "/static/js/453.d9749a7d.chunk.js.map",
|
||||
"664.02d4d120.css.map": "/static/css/664.02d4d120.css.map",
|
||||
"664.d9b6a63b.js.map": "/static/js/664.d9b6a63b.js.map"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/js/runtime.0b5f0839.js",
|
||||
"static/css/664.02d4d120.css",
|
||||
"static/js/664.d9b6a63b.js",
|
||||
"static/css/main.e9950038.css",
|
||||
"static/js/main.dd323bc8.js"
|
||||
]
|
||||
}
|
||||
@@ -1 +1,29 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"/><meta name="theme-color" content="#000000"/><meta name="color-scheme" content="light dark"/><meta name="description" content="Oficiální webové stránky fotbalového klubu - aktuality, zápasy, tabulky, hráči a fotogalerie"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><link rel="preconnect" href="https://fonts.googleapis.com"/><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/><link rel="preconnect" href="https://www.youtube.com" crossorigin/><link rel="preconnect" href="https://i.ytimg.com" crossorigin/><link rel="preconnect" href="https://s.ytimg.com" crossorigin/><link rel="preconnect" href="https://www.google.com" crossorigin/><title>Fotbal Club</title><script defer="defer" src="/static/js/runtime.0b5f0839.js"></script><script defer="defer" src="/static/js/664.d9b6a63b.js"></script><script defer="defer" src="/static/js/main.dd323bc8.js"></script><link href="/static/css/664.02d4d120.css" rel="stylesheet"><link href="/static/css/main.e9950038.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="color-scheme" content="light dark" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Oficiální webové stránky fotbalového klubu - aktuality, zápasy, tabulky, hráči a fotogalerie"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="/logo192.png" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link rel="preconnect" href="https://www.youtube.com" crossorigin />
|
||||
<link rel="preconnect" href="https://i.ytimg.com" crossorigin />
|
||||
<link rel="preconnect" href="https://s.ytimg.com" crossorigin />
|
||||
<link rel="preconnect" href="https://www.google.com" crossorigin />
|
||||
<title>Fotbal Club</title>
|
||||
<script type="module" crossorigin src="/static/index-CLCx9azl.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/static/index-BHzfWAR3.css">
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 9.4 KiB |
@@ -1 +1,26 @@
|
||||
{"short_name": "Fotbal Club", "name": "Fotbal Club - Oficiální aplikace", "description": "Oficiální webové stránky fotbalového klubu - aktuality, zápasy, tabulky, hráči a fotogalerie", "icons": [{"src": "favicon.ico", "sizes": "64x64 32x32 24x24 16x16", "type": "image/x-icon"}, {"src": "logo192.png", "type": "image/png", "sizes": "192x192"}, {"src": "logo512.png", "type": "image/png", "sizes": "512x512"}], "start_url": ".", "display": "standalone", "theme_color": "#000000", "background_color": "#ffffff"}
|
||||
{
|
||||
"short_name": "Fotbal Club",
|
||||
"name": "Fotbal Club - Oficiální aplikace",
|
||||
"description": "Oficiální webové stránky fotbalového klubu - aktuality, zápasy, tabulky, hráči a fotogalerie",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png?v=2",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png?v=2",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
// Service Worker for PWA support and offline functionality
|
||||
|
||||
const CACHE_VERSION = 'v1.0.2';
|
||||
const CACHE_VERSION = 'v1.0.3';
|
||||
const CACHE_NAME = `fotbal-club-cache-${CACHE_VERSION}`;
|
||||
|
||||
// Rate limiting for background updates
|
||||
@@ -14,8 +14,8 @@ const STATIC_ASSETS = [
|
||||
'/index.html',
|
||||
'/manifest.json',
|
||||
'/favicon.ico',
|
||||
'/logo192.png',
|
||||
'/logo512.png',
|
||||
'/logo192.png?v=2',
|
||||
'/logo512.png?v=2',
|
||||
'/robots.txt',
|
||||
];
|
||||
|
||||
@@ -266,8 +266,8 @@ self.addEventListener('push', (event) => {
|
||||
const title = data.title || 'Fotbal Club';
|
||||
const options = {
|
||||
body: data.body || 'Nová notifikace',
|
||||
icon: '/logo192.png',
|
||||
badge: '/logo192.png',
|
||||
icon: '/logo192.png?v=2',
|
||||
badge: '/logo192.png?v=2',
|
||||
data: data.url || '/',
|
||||
};
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
"use strict";(self.webpackChunkfrontend=self.webpackChunkfrontend||[]).push([[118],{58118:(e,t,r)=>{r.r(t),r.d(t,{default:()=>m});var o=r(65043),s=r(22107),n=r(98662),i=r(25011),a=r(10202),l=r(28846),c=r(39081),h=r(1009),u=r(70579);class d extends o.Component{constructor(e){super(e),this.resetTimeout=null,this.scheduleAutoReset=()=>{this.resetTimeout&&clearTimeout(this.resetTimeout),this.resetTimeout=setTimeout(()=>{this.handleReset()},3e3)},this.handleReset=()=>{this.resetTimeout&&(clearTimeout(this.resetTimeout),this.resetTimeout=null),this.cleanupDOMElements(),this.setState({hasError:!1,error:null,errorInfo:null}),this.props.onReset&&this.props.onReset()},this.cleanupDOMElements=()=>{try{document.querySelectorAll(".elementor-overlay").forEach(e=>{try{e.remove()}catch(t){console.warn("Failed to remove overlay:",t)}});const c=document.querySelector(".myuibrix-viewport-wrapper");if(c&&c.parentElement)try{const l=c.parentElement;if(l.hasAttribute("data-myuibrix-restore"))Array.from(c.children).forEach(e=>{try{l.appendChild(e)}catch(t){console.warn("Failed to move child:",t)}}),c.remove(),l.removeAttribute("data-myuibrix-restore");else{try{c.classList.remove("myuibrix-viewport-wrapper")}catch(e){}try{c.removeAttribute("data-myuibrix-wrapped")}catch(t){}try{c.style.width=""}catch(r){}try{c.style.maxWidth=""}catch(o){}try{c.style.transition=""}catch(s){}try{c.style.margin=""}catch(n){}try{c.style.transform=""}catch(i){}try{c.style.transformOrigin=""}catch(a){}}}catch(l){console.warn("Failed to cleanup viewport wrapper:",l)}document.body.style.paddingTop="0",document.body.style.backgroundColor="",document.body.style.userSelect=""}catch(l){console.error("Error during DOM cleanup:",l)}},this.state={hasError:!1,error:null,errorInfo:null,errorCount:0}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}componentDidCatch(e,t){console.error("MyUIbrix Error Boundary caught an error:",e,t),this.setState(e=>({errorInfo:t,errorCount:e.errorCount+1})),(e.message.includes("removeChild")||e.message.includes("insertBefore")||e.message.includes("replaceChild")||"DOMException"===e.name)&&(console.warn("DOM manipulation error detected - will auto-reset in 3 seconds"),this.scheduleAutoReset())}componentWillUnmount(){this.resetTimeout&&clearTimeout(this.resetTimeout)}render(){if(this.state.hasError&&this.state.error){const e=this.state.error.message.includes("removeChild")||this.state.error.message.includes("insertBefore")||this.state.error.message.includes("replaceChild")||"DOMException"===this.state.error.name;return(0,u.jsx)(s.a,{position:"fixed",top:"0",left:"0",right:"0",bottom:"0",bg:"rgba(0, 0, 0, 0.85)",backdropFilter:"blur(8px)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:99999,children:(0,u.jsxs)(a.T,{spacing:6,bg:"white",p:8,borderRadius:"2xl",boxShadow:"0 20px 60px rgba(0,0,0,0.5)",maxW:"600px",w:"90%",children:[(0,u.jsx)(i.I,{as:h.eHT,boxSize:16,color:"orange.500"}),(0,u.jsxs)(a.T,{spacing:2,children:[(0,u.jsx)(l.D,{size:"lg",color:"gray.800",children:e?"Chyba p\u0159i manipulaci s prvky":"Chyba editoru"}),(0,u.jsx)(c.E,{color:"gray.600",textAlign:"center",children:e?"Nastala chyba p\u0159i p\u0159esouv\xe1n\xed nebo upravov\xe1n\xed prvk\u016f. Editor se automaticky obnov\xed za 3 sekundy.":"V editoru nastala neo\u010dek\xe1van\xe1 chyba. Klikn\u011bte na tla\u010d\xedtko pro obnoven\xed."})]}),!1,(0,u.jsxs)(a.T,{spacing:3,w:"100%",children:[(0,u.jsx)(n.$,{leftIcon:(0,u.jsx)(h.jTZ,{}),colorScheme:"blue",size:"lg",w:"100%",onClick:this.handleReset,children:"Obnovit editor"}),this.state.errorCount>3&&(0,u.jsxs)(c.E,{fontSize:"sm",color:"orange.600",textAlign:"center",children:["\u26a0\ufe0f Opakovan\xe9 chyby (",this.state.errorCount,"x). Zva\u017ete obnoven\xed str\xe1nky."]}),this.state.errorCount>3&&(0,u.jsx)(n.$,{size:"sm",variant:"ghost",colorScheme:"gray",onClick:()=>window.location.reload(),children:"Obnovit celou str\xe1nku"})]})]})})}return this.props.children}}const m=d}}]);
|
||||
//# sourceMappingURL=118.8a550f36.chunk.js.map
|
||||
@@ -1,2 +0,0 @@
|
||||
"use strict";(self.webpackChunkfrontend=self.webpackChunkfrontend||[]).push([[453],{46453:(e,t,n)=>{n.r(t),n.d(t,{getCLS:()=>y,getFCP:()=>g,getFID:()=>C,getLCP:()=>P,getTTFB:()=>D});var i,r,a,o,u=function(e,t){return{name:e,value:void 0===t?-1:t,delta:0,entries:[],id:"v2-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12)}},c=function(e,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){if("first-input"===e&&!("PerformanceEventTiming"in self))return;var n=new PerformanceObserver(function(e){return e.getEntries().map(t)});return n.observe({type:e,buffered:!0}),n}}catch(e){}},f=function(e,t){var n=function n(i){"pagehide"!==i.type&&"hidden"!==document.visibilityState||(e(i),t&&(removeEventListener("visibilitychange",n,!0),removeEventListener("pagehide",n,!0)))};addEventListener("visibilitychange",n,!0),addEventListener("pagehide",n,!0)},s=function(e){addEventListener("pageshow",function(t){t.persisted&&e(t)},!0)},m=function(e,t,n){var i;return function(r){t.value>=0&&(r||n)&&(t.delta=t.value-(i||0),(t.delta||void 0===i)&&(i=t.value,e(t)))}},v=-1,d=function(){return"hidden"===document.visibilityState?0:1/0},p=function(){f(function(e){var t=e.timeStamp;v=t},!0)},l=function(){return v<0&&(v=d(),p(),s(function(){setTimeout(function(){v=d(),p()},0)})),{get firstHiddenTime(){return v}}},g=function(e,t){var n,i=l(),r=u("FCP"),a=function(e){"first-contentful-paint"===e.name&&(f&&f.disconnect(),e.startTime<i.firstHiddenTime&&(r.value=e.startTime,r.entries.push(e),n(!0)))},o=window.performance&&performance.getEntriesByName&&performance.getEntriesByName("first-contentful-paint")[0],f=o?null:c("paint",a);(o||f)&&(n=m(e,r,t),o&&a(o),s(function(i){r=u("FCP"),n=m(e,r,t),requestAnimationFrame(function(){requestAnimationFrame(function(){r.value=performance.now()-i.timeStamp,n(!0)})})}))},h=!1,T=-1,y=function(e,t){h||(g(function(e){T=e.value}),h=!0);var n,i=function(t){T>-1&&e(t)},r=u("CLS",0),a=0,o=[],v=function(e){if(!e.hadRecentInput){var t=o[0],i=o[o.length-1];a&&e.startTime-i.startTime<1e3&&e.startTime-t.startTime<5e3?(a+=e.value,o.push(e)):(a=e.value,o=[e]),a>r.value&&(r.value=a,r.entries=o,n())}},d=c("layout-shift",v);d&&(n=m(i,r,t),f(function(){d.takeRecords().map(v),n(!0)}),s(function(){a=0,T=-1,r=u("CLS",0),n=m(i,r,t)}))},E={passive:!0,capture:!0},w=new Date,L=function(e,t){i||(i=t,r=e,a=new Date,F(removeEventListener),S())},S=function(){if(r>=0&&r<a-w){var e={entryType:"first-input",name:i.type,target:i.target,cancelable:i.cancelable,startTime:i.timeStamp,processingStart:i.timeStamp+r};o.forEach(function(t){t(e)}),o=[]}},b=function(e){if(e.cancelable){var t=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;"pointerdown"==e.type?function(e,t){var n=function(){L(e,t),r()},i=function(){r()},r=function(){removeEventListener("pointerup",n,E),removeEventListener("pointercancel",i,E)};addEventListener("pointerup",n,E),addEventListener("pointercancel",i,E)}(t,e):L(t,e)}},F=function(e){["mousedown","keydown","touchstart","pointerdown"].forEach(function(t){return e(t,b,E)})},C=function(e,t){var n,a=l(),v=u("FID"),d=function(e){e.startTime<a.firstHiddenTime&&(v.value=e.processingStart-e.startTime,v.entries.push(e),n(!0))},p=c("first-input",d);n=m(e,v,t),p&&f(function(){p.takeRecords().map(d),p.disconnect()},!0),p&&s(function(){var a;v=u("FID"),n=m(e,v,t),o=[],r=-1,i=null,F(addEventListener),a=d,o.push(a),S()})},k={},P=function(e,t){var n,i=l(),r=u("LCP"),a=function(e){var t=e.startTime;t<i.firstHiddenTime&&(r.value=t,r.entries.push(e),n())},o=c("largest-contentful-paint",a);if(o){n=m(e,r,t);var v=function(){k[r.id]||(o.takeRecords().map(a),o.disconnect(),k[r.id]=!0,n(!0))};["keydown","click"].forEach(function(e){addEventListener(e,v,{once:!0,capture:!0})}),f(v,!0),s(function(i){r=u("LCP"),n=m(e,r,t),requestAnimationFrame(function(){requestAnimationFrame(function(){r.value=performance.now()-i.timeStamp,k[r.id]=!0,n(!0)})})})}},D=function(e){var t,n=u("TTFB");t=function(){try{var t=performance.getEntriesByType("navigation")[0]||function(){var e=performance.timing,t={entryType:"navigation",startTime:0};for(var n in e)"navigationStart"!==n&&"toJSON"!==n&&(t[n]=Math.max(e[n]-e.navigationStart,0));return t}();if(n.value=n.delta=t.responseStart,n.value<0||n.value>performance.now())return;n.entries=[t],e(n)}catch(e){}},"complete"===document.readyState?setTimeout(t,0):addEventListener("load",function(){return setTimeout(t,0)})}}}]);
|
||||
//# sourceMappingURL=453.d9749a7d.chunk.js.map
|
||||
@@ -1,2 +0,0 @@
|
||||
"use strict";(self.webpackChunkfrontend=self.webpackChunkfrontend||[]).push([[469],{69469:(e,r,t)=>{t.r(r),t.d(r,{default:()=>c});var a=t(89379),n=(t(65043),t(22107)),i=t(7189),o=t(25189),l=t(70579);const c=e=>{let{banners:r,placement:t,containerStyle:c}=e;const s=(r||[]).filter(e=>e.placement===t&&!1!==e.is_active);if(0===s.length)return null;const d=(0,a.A)((0,a.A)({},(()=>{const e={margin:"24px 0",display:"flex",justifyContent:"center",alignItems:"center",gap:"16px",flexWrap:"wrap"};switch(t){case"homepage_top":return(0,a.A)((0,a.A)({},e),{},{width:"100vw",position:"relative",left:"50%",right:"50%",marginLeft:"-50vw",marginRight:"-50vw",backgroundColor:"rgba(0, 0, 0, 0.02)",padding:"16px",borderTop:"1px solid rgba(0, 0, 0, 0.05)",borderBottom:"1px solid rgba(0, 0, 0, 0.05)"});case"homepage_footer":return(0,a.A)((0,a.A)({},e),{},{width:"100vw",position:"relative",left:"50%",right:"50%",marginLeft:"-50vw",marginRight:"-50vw",backgroundColor:"rgba(0, 0, 0, 0.02)",padding:"24px 16px",borderTop:"1px solid rgba(0, 0, 0, 0.05)"});case"homepage_under_table":return(0,a.A)((0,a.A)({},e),{},{margin:"12px 0 0",justifyContent:"center"});default:return e}})()),c);return(0,l.jsx)(n.a,{as:"section",className:(()=>{switch(t){case"homepage_top":return"banner-top";case"homepage_middle":return"banner-middle";case"homepage_footer":return"banner-footer";case"article_inline":return"banner-article";case"homepage_under_table":return"banner-under-table";default:return"banner"}})(),sx:d,children:s.map(e=>(0,l.jsx)(i.N,{href:e.url||e.click_url||"#",isExternal:!(!e.url&&!e.click_url),target:e.url||e.click_url?"_blank":void 0,rel:e.url||e.click_url?"noopener noreferrer":void 0,display:"inline-block",_hover:{opacity:.9,transform:"translateY(-2px)"},transition:"all 0.2s",children:(0,l.jsx)("img",{src:(0,o.uq)(e.image||e.image_url||"")||e.image||e.image_url||"",alt:e.name,style:{maxWidth:"100%",width:e.width?"".concat(e.width,"px"):"auto",height:e.height?"".concat(e.height,"px"):"auto",objectFit:"contain",borderRadius:"4px",boxShadow:"none"},loading:"lazy"})},e.id))})}}}]);
|
||||
//# sourceMappingURL=469.ec731235.chunk.js.map
|
||||
@@ -1,2 +0,0 @@
|
||||
"use strict";(self.webpackChunkfrontend=self.webpackChunkfrontend||[]).push([[771],{69771:(e,l,s)=>{s.r(l),s.d(l,{default:()=>x});s(65043);var a=s(22107),n=s(44093),i=s(76659),t=s(10202),d=s(28846),r=s(39081),c=s(72526),o=s(71093),u=s(35349),p=s(70579);const x=e=>{let{featuredOnly:l=!0,maxPolls:s=1,title:x="Hlasov\xe1n\xed"}=e;const h=(0,n.dU)("gray.50","gray.900"),{data:g,isLoading:y}=(0,c.I)({queryKey:["polls",{featured:l}],queryFn:()=>(0,o.Ps)(l?{featured:!0}:void 0),staleTime:12e4}),f=(null===g||void 0===g?void 0:g.slice(0,s))||[],{data:j,isLoading:m}=(0,c.I)({queryKey:["polls-details",f.map(e=>e.id)],queryFn:async()=>{const e=f.map(e=>(0,o.gU)(e.id));return await Promise.all(e)},enabled:f.length>0});return y||m?(0,p.jsx)(a.a,{bg:h,py:12,px:4,children:(0,p.jsxs)(t.T,{spacing:4,children:[(0,p.jsx)(i.y,{size:"lg"}),(0,p.jsx)(r.E,{children:"Na\u010d\xedt\xe1n\xed ankety..."})]})}):j&&0!==j.length?(0,p.jsx)(a.a,{bg:h,py:12,px:4,children:(0,p.jsxs)(t.T,{spacing:8,maxW:"4xl",mx:"auto",children:[(0,p.jsx)(d.D,{size:"lg",textAlign:"center",children:x}),(0,p.jsx)(t.T,{spacing:6,w:"full",children:j.map(e=>(0,p.jsx)(a.a,{w:"full",maxW:"600px",children:(0,p.jsx)(u.A,{poll:e.poll,hasVoted:e.has_voted,isActive:e.is_active,canShowResults:e.can_show_results})},e.poll.id))})]})}):null}}}]);
|
||||
//# sourceMappingURL=771.2b2378c2.chunk.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"static/js/771.2b2378c2.chunk.js","mappings":"6PAqBA,MAiEA,EAjEgDA,IAIzC,IAJ0C,aAC/CC,GAAe,EAAI,SACnBC,EAAW,EAAC,MACZC,EAAQ,mBACTH,EACC,MAAMI,GAAYC,EAAAA,EAAAA,IAAkB,UAAW,aAGvCC,KAAMC,EAAK,UAAEC,IAAcC,EAAAA,EAAAA,GAAS,CAC1CC,SAAU,CAAC,QAAS,CAAEC,SAAUV,IAChCW,QAASA,KAAMC,EAAAA,EAAAA,IAASZ,EAAe,CAAEU,UAAU,QAASG,GAC5DC,UAAW,OAIPC,GAAsB,OAALT,QAAK,IAALA,OAAK,EAALA,EAAOU,MAAM,EAAGf,KAAa,IAE5CI,KAAMY,EAAWV,UAAWW,IAAmBV,EAAAA,EAAAA,GAAS,CAC9DC,SAAU,CAAC,gBAAiBM,EAAeI,IAAKC,GAAMA,EAAEC,KACxDV,QAASW,UACP,MAAMC,EAAWR,EAAeI,IAAKK,IAASC,EAAAA,EAAAA,IAAQD,EAAKH,KAC3D,aAAaK,QAAQC,IAAIJ,IAE3BK,QAASb,EAAec,OAAS,IAGnC,OAAItB,GAAaW,GAEbY,EAAAA,EAAAA,KAACC,EAAAA,EAAG,CAACC,GAAI7B,EAAW8B,GAAI,GAAIC,GAAI,EAAEC,UAChCC,EAAAA,EAAAA,MAACC,EAAAA,EAAM,CAACC,QAAS,EAAEH,SAAA,EACjBL,EAAAA,EAAAA,KAACS,EAAAA,EAAO,CAACC,KAAK,QACdV,EAAAA,EAAAA,KAACW,EAAAA,EAAI,CAAAN,SAAC,0CAMTlB,GAAkC,IAArBA,EAAUY,QAK1BC,EAAAA,EAAAA,KAACC,EAAAA,EAAG,CAACC,GAAI7B,EAAW8B,GAAI,GAAIC,GAAI,EAAEC,UAChCC,EAAAA,EAAAA,MAACC,EAAAA,EAAM,CAACC,QAAS,EAAGI,KAAK,MAAMC,GAAG,OAAMR,SAAA,EACtCL,EAAAA,EAAAA,KAACc,EAAAA,EAAO,CAACJ,KAAK,KAAKK,UAAU,SAAQV,SAClCjC,KAGH4B,EAAAA,EAAAA,KAACO,EAAAA,EAAM,CAACC,QAAS,EAAGQ,EAAE,OAAMX,SACzBlB,EAAUE,IAAK4B,IACdjB,EAAAA,EAAAA,KAACC,EAAAA,EAAG,CAA4Be,EAAE,OAAOJ,KAAK,QAAOP,UACnDL,EAAAA,EAAAA,KAACkB,EAAAA,EAAQ,CACPxB,KAAMuB,EAAavB,KACnByB,SAAUF,EAAaG,UACvBC,SAAUJ,EAAaK,UACvBC,eAAgBN,EAAaO,oBALvBP,EAAavB,KAAKH,YAZ7B,K","sources":["components/home/PollsWidget.tsx"],"sourcesContent":["import React from 'react';\nimport {\n Box,\n VStack,\n Heading,\n Text,\n Spinner,\n Alert,\n AlertIcon,\n useColorModeValue,\n} from '@chakra-ui/react';\nimport { useQuery } from '@tanstack/react-query';\nimport { getPolls, getPoll } from '../../services/polls';\nimport PollCard from '../polls/PollCard';\n\ninterface PollsWidgetProps {\n featuredOnly?: boolean;\n maxPolls?: number;\n title?: string;\n}\n\nconst PollsWidget: React.FC<PollsWidgetProps> = ({\n featuredOnly = true,\n maxPolls = 1,\n title = 'Hlasování',\n}) => {\n const bgSection = useColorModeValue('gray.50', 'gray.900');\n\n // Fetch polls list\n const { data: polls, isLoading } = useQuery({\n queryKey: ['polls', { featured: featuredOnly }],\n queryFn: () => getPolls(featuredOnly ? { featured: true } : undefined),\n staleTime: 2 * 60 * 1000, // 2 minutes\n });\n\n // Get full poll data for each featured poll\n const pollsToDisplay = polls?.slice(0, maxPolls) || [];\n\n const { data: pollsData, isLoading: isLoadingPolls } = useQuery({\n queryKey: ['polls-details', pollsToDisplay.map((p) => p.id)],\n queryFn: async () => {\n const promises = pollsToDisplay.map((poll) => getPoll(poll.id));\n return await Promise.all(promises);\n },\n enabled: pollsToDisplay.length > 0,\n });\n\n if (isLoading || isLoadingPolls) {\n return (\n <Box bg={bgSection} py={12} px={4}>\n <VStack spacing={4}>\n <Spinner size=\"lg\" />\n <Text>Načítání ankety...</Text>\n </VStack>\n </Box>\n );\n }\n\n if (!pollsData || pollsData.length === 0) {\n return null; // Don't show widget if no polls\n }\n\n return (\n <Box bg={bgSection} py={12} px={4}>\n <VStack spacing={8} maxW=\"4xl\" mx=\"auto\">\n <Heading size=\"lg\" textAlign=\"center\">\n {title}\n </Heading>\n\n <VStack spacing={6} w=\"full\">\n {pollsData.map((pollResponse) => (\n <Box key={pollResponse.poll.id} w=\"full\" maxW=\"600px\">\n <PollCard\n poll={pollResponse.poll}\n hasVoted={pollResponse.has_voted}\n isActive={pollResponse.is_active}\n canShowResults={pollResponse.can_show_results}\n />\n </Box>\n ))}\n </VStack>\n </VStack>\n </Box>\n );\n};\n\nexport default PollsWidget;\n"],"names":["_ref","featuredOnly","maxPolls","title","bgSection","useColorModeValue","data","polls","isLoading","useQuery","queryKey","featured","queryFn","getPolls","undefined","staleTime","pollsToDisplay","slice","pollsData","isLoadingPolls","map","p","id","async","promises","poll","getPoll","Promise","all","enabled","length","_jsx","Box","bg","py","px","children","_jsxs","VStack","spacing","Spinner","size","Text","maxW","mx","Heading","textAlign","w","pollResponse","PollCard","hasVoted","has_voted","isActive","is_active","canShowResults","can_show_results"],"sourceRoot":""}
|
||||
@@ -1,2 +0,0 @@
|
||||
"use strict";(self.webpackChunkfrontend=self.webpackChunkfrontend||[]).push([[798],{78798:(e,s,n)=>{n.r(s),n.d(s,{default:()=>o});n(65043);var a=n(74117),l=n(22107),i=n(98662),r=n(98939),c=n(10202),d=n(39081),t=n(70579);const o=()=>{const{t:e,i18n:s}=(0,a.Bd)();return(0,t.jsx)(r.m,{maxW:"container.md",py:8,children:(0,t.jsx)(l.a,{p:4,borderWidth:1,borderRadius:"md",children:(0,t.jsxs)(c.T,{spacing:4,align:"start",children:[(0,t.jsx)(d.E,{fontSize:"2xl",fontWeight:"bold",children:"i18n Test Page"}),(0,t.jsxs)(d.E,{children:["Current language: ",(0,t.jsx)("strong",{children:s.language})]}),(0,t.jsxs)(d.E,{children:["Is ready: ",s.isInitialized?"Yes":"No"]}),(0,t.jsxs)(d.E,{children:["Loaded languages: ",s.languages.join(", ")]}),(0,t.jsxs)(l.a,{borderWidth:1,p:3,borderRadius:"md",w:"full",children:[(0,t.jsx)(d.E,{fontWeight:"bold",children:"Translation tests:"}),(0,t.jsxs)(d.E,{children:["Welcome: ",e("common.welcome_message")]}),(0,t.jsxs)(d.E,{children:["Subtitle: ",e("common.welcome_subtitle")]}),(0,t.jsxs)(d.E,{children:["Home: ",e("nav.home")]}),(0,t.jsxs)(d.E,{children:["Matches: ",e("nav.matches")]}),(0,t.jsxs)(d.E,{children:["Gallery: ",e("nav.gallery")]}),(0,t.jsxs)(d.E,{children:["Save: ",e("action.save")]}),(0,t.jsxs)(d.E,{children:["Loading: ",e("message.loading")]})]}),(0,t.jsxs)(i.$,{onClick:()=>{const e="cs"===s.language?"en":"cs";s.changeLanguage(e)},colorScheme:"blue",children:["Switch to ","cs"===s.language?"English":"\u010ce\u0161tina"]})]})})})}}}]);
|
||||
//# sourceMappingURL=798.21001033.chunk.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"static/js/798.21001033.chunk.js","mappings":"4NAIA,MAqCA,EArC+BA,KAC7B,MAAM,EAAEC,EAAC,KAAEC,IAASC,EAAAA,EAAAA,MAOpB,OACEC,EAAAA,EAAAA,KAACC,EAAAA,EAAS,CAACC,KAAK,eAAeC,GAAI,EAAEC,UACnCJ,EAAAA,EAAAA,KAACK,EAAAA,EAAG,CAACC,EAAG,EAAGC,YAAa,EAAGC,aAAa,KAAIJ,UAC1CK,EAAAA,EAAAA,MAACC,EAAAA,EAAM,CAACC,QAAS,EAAGC,MAAM,QAAOR,SAAA,EAC/BJ,EAAAA,EAAAA,KAACa,EAAAA,EAAI,CAACC,SAAS,MAAMC,WAAW,OAAMX,SAAC,oBACvCK,EAAAA,EAAAA,MAACI,EAAAA,EAAI,CAAAT,SAAA,CAAC,sBAAkBJ,EAAAA,EAAAA,KAAA,UAAAI,SAASN,EAAKkB,eACtCP,EAAAA,EAAAA,MAACI,EAAAA,EAAI,CAAAT,SAAA,CAAC,aAAWN,EAAKmB,cAAgB,MAAQ,SAC9CR,EAAAA,EAAAA,MAACI,EAAAA,EAAI,CAAAT,SAAA,CAAC,qBAAmBN,EAAKoB,UAAUC,KAAK,UAE7CV,EAAAA,EAAAA,MAACJ,EAAAA,EAAG,CAACE,YAAa,EAAGD,EAAG,EAAGE,aAAa,KAAKY,EAAE,OAAMhB,SAAA,EACnDJ,EAAAA,EAAAA,KAACa,EAAAA,EAAI,CAACE,WAAW,OAAMX,SAAC,wBACxBK,EAAAA,EAAAA,MAACI,EAAAA,EAAI,CAAAT,SAAA,CAAC,YAAUP,EAAE,8BAClBY,EAAAA,EAAAA,MAACI,EAAAA,EAAI,CAAAT,SAAA,CAAC,aAAWP,EAAE,+BACnBY,EAAAA,EAAAA,MAACI,EAAAA,EAAI,CAAAT,SAAA,CAAC,SAAOP,EAAE,gBACfY,EAAAA,EAAAA,MAACI,EAAAA,EAAI,CAAAT,SAAA,CAAC,YAAUP,EAAE,mBAClBY,EAAAA,EAAAA,MAACI,EAAAA,EAAI,CAAAT,SAAA,CAAC,YAAUP,EAAE,mBAClBY,EAAAA,EAAAA,MAACI,EAAAA,EAAI,CAAAT,SAAA,CAAC,SAAOP,EAAE,mBACfY,EAAAA,EAAAA,MAACI,EAAAA,EAAI,CAAAT,SAAA,CAAC,YAAUP,EAAE,0BAGpBY,EAAAA,EAAAA,MAACY,EAAAA,EAAM,CAACC,QAzBOC,KACrB,MAAMC,EAA4B,OAAlB1B,EAAKkB,SAAoB,KAAO,KAChDlB,EAAK2B,eAAeD,IAuBmBE,YAAY,OAAMtB,SAAA,CAAC,aACrB,OAAlBN,EAAKkB,SAAoB,UAAY,8B","sources":["pages/I18nTestPage.tsx"],"sourcesContent":["import React from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Box, Text, Button, VStack, Container } from '@chakra-ui/react';\n\nconst I18nTestPage: React.FC = () => {\n const { t, i18n } = useTranslation();\n\n const toggleLanguage = () => {\n const newLang = i18n.language === 'cs' ? 'en' : 'cs';\n i18n.changeLanguage(newLang);\n };\n\n return (\n <Container maxW=\"container.md\" py={8}>\n <Box p={4} borderWidth={1} borderRadius=\"md\">\n <VStack spacing={4} align=\"start\">\n <Text fontSize=\"2xl\" fontWeight=\"bold\">i18n Test Page</Text>\n <Text>Current language: <strong>{i18n.language}</strong></Text>\n <Text>Is ready: {i18n.isInitialized ? 'Yes' : 'No'}</Text>\n <Text>Loaded languages: {i18n.languages.join(', ')}</Text>\n \n <Box borderWidth={1} p={3} borderRadius=\"md\" w=\"full\">\n <Text fontWeight=\"bold\">Translation tests:</Text>\n <Text>Welcome: {t('common.welcome_message')}</Text>\n <Text>Subtitle: {t('common.welcome_subtitle')}</Text>\n <Text>Home: {t('nav.home')}</Text>\n <Text>Matches: {t('nav.matches')}</Text>\n <Text>Gallery: {t('nav.gallery')}</Text>\n <Text>Save: {t('action.save')}</Text>\n <Text>Loading: {t('message.loading')}</Text>\n </Box>\n \n <Button onClick={toggleLanguage} colorScheme=\"blue\">\n Switch to {i18n.language === 'cs' ? 'English' : 'Čeština'}\n </Button>\n </VStack>\n </Box>\n </Container>\n );\n};\n\nexport default I18nTestPage;\n"],"names":["I18nTestPage","t","i18n","useTranslation","_jsx","Container","maxW","py","children","Box","p","borderWidth","borderRadius","_jsxs","VStack","spacing","align","Text","fontSize","fontWeight","language","isInitialized","languages","join","w","Button","onClick","toggleLanguage","newLang","changeLanguage","colorScheme"],"sourceRoot":""}
|
||||
@@ -1,2 +0,0 @@
|
||||
"use strict";(self.webpackChunkfrontend=self.webpackChunkfrontend||[]).push([[910],{15910:(e,i,r)=>{r.r(i),r.d(i,{default:()=>z});r(65043);var t=r(87139),a=r(22107),o=r(98662),s=r(44093),n=r(33572),l=r(99032),d=r(96148),c=r(10202),p=r(28846),g=r(39081),h=r(72526),u=r(34636),x=r(70118),m=r(35475),b=r(78801),f=r(25189),j=r(75088),v=r(35087),w=r(12255),y=r(70579);const _=e=>{var i;let{a:r}=e;const o=(0,s.dU)("white","gray.800"),l=(0,s.dU)("gray.200","whiteAlpha.300"),h=((0,b.N)(),r.slug?"/news/".concat(r.slug):"/articles/".concat(r.id)),u=((0,s.dU)("gray.100","whiteAlpha.200"),(null===r||void 0===r||null===(i=r.category)||void 0===i?void 0:i.name)||"");return(0,y.jsxs)(a.a,{as:m.N_,to:h,minW:{base:"85%",md:"60%",lg:"33%"},scrollSnapAlign:"start",bg:o,borderRadius:"xl",overflow:"hidden",boxShadow:"lg",borderWidth:"1px",borderColor:l,_hover:{transform:"translateY(-4px)",boxShadow:"2xl"},transition:"all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",position:"relative",children:[(0,y.jsxs)(a.a,{position:"relative",overflow:"hidden",children:[(0,y.jsx)(n._,{src:(0,f.uq)(r.image_url)||"/stadium-placeholder.jpg",alt:r.title,w:"100%",h:{base:"200px",md:"240px"},objectFit:"cover",transition:"transform 0.3s ease",_groupHover:{transform:"scale(1.05)"}}),u&&(0,y.jsx)(t.E,{position:"absolute",top:3,left:3,colorScheme:"blue",fontSize:"xs",px:3,py:1,borderRadius:"full",textTransform:"uppercase",fontWeight:"bold",children:u})]}),(0,y.jsxs)(c.T,{align:"stretch",spacing:3,p:5,children:[(0,y.jsx)(p.D,{size:"md",noOfLines:2,lineHeight:"1.3",children:r.title}),r.content&&(0,y.jsx)(g.E,{fontSize:"sm",color:"gray.600",noOfLines:3,lineHeight:"1.5",children:r.content.replace(/<[^>]*>/g,"").trim()}),(0,y.jsxs)(d.z,{spacing:3,pt:2,borderTopWidth:"1px",borderColor:l,flexWrap:"wrap",children:[(r.read_time||r.estimated_read_minutes)&&(0,y.jsxs)(d.z,{spacing:1,children:[(0,y.jsx)(j.A,{size:14,color:"gray"}),(0,y.jsxs)(g.E,{fontSize:"xs",color:"gray.500",children:[r.read_time||r.estimated_read_minutes," min"]})]}),void 0!==r.view_count&&r.view_count>0&&(0,y.jsxs)(d.z,{spacing:1,children:[(0,y.jsx)(v.A,{size:14,color:"gray"}),(0,y.jsx)(g.E,{fontSize:"xs",color:"gray.500",children:r.view_count})]}),r.published_at&&(0,y.jsx)(g.E,{fontSize:"xs",color:"gray.500",children:new Date(r.published_at).toLocaleDateString("cs-CZ")})]})]}),(0,y.jsx)(w.A,{article:r,targetUrl:"undefined"!==typeof window?new URL(h,window.location.origin).toString():void 0,placement:"inline",position:"bottom-right",size:"sm"})]})},z=()=>{(0,b.N)();const{data:e,isLoading:i}=(0,h.I)({queryKey:["articles",{page:1,page_size:12,published:!0}],queryFn:()=>(0,u.GE)({page:1,page_size:12,published:!0})}),{data:r}=(0,h.I)({queryKey:["articles","featured",{page:1,page_size:100}],queryFn:()=>(0,u.A0)({page:1,page_size:100})}),t=(null===e||void 0===e?void 0:e.data)||[],s=new Set(((null===r||void 0===r?void 0:r.data)||[]).map(e=>e.slug?"s:".concat(e.slug):"i:".concat(e.id))),n=t.filter(e=>!s.has(e.slug?"s:".concat(e.slug):"i:".concat(e.id)));return(0,y.jsx)(a.a,{children:(0,y.jsxs)(x.A,{title:"Novinky",rightAction:(0,y.jsx)(o.$,{as:m.N_,to:"/blog",variant:"link",color:"brand.primary",children:"V\xedce"}),children:[i&&Array.from({length:4}).map((e,i)=>(0,y.jsx)(l.E,{minW:{base:"85%",md:"60%",lg:"33%"},h:{base:"260px",md:"300px"},borderRadius:"xl"},i)),!i&&n.map(e=>(0,y.jsx)(_,{a:e},e.id))]})})}}}]);
|
||||
//# sourceMappingURL=910.bec7c150.chunk.js.map
|
||||
@@ -1,2 +0,0 @@
|
||||
(()=>{"use strict";var e={},t={};function r(o){var n=t[o];if(void 0!==n)return n.exports;var a=t[o]={id:o,loaded:!1,exports:{}};return e[o].call(a.exports,a,a.exports,r),a.loaded=!0,a.exports}r.m=e,(()=>{var e=[];r.O=(t,o,n,a)=>{if(!o){var i=1/0;for(l=0;l<e.length;l++){o=e[l][0],n=e[l][1],a=e[l][2];for(var d=!0,c=0;c<o.length;c++)(!1&a||i>=a)&&Object.keys(r.O).every(e=>r.O[e](o[c]))?o.splice(c--,1):(d=!1,a<i&&(i=a));if(d){e.splice(l--,1);var f=n();void 0!==f&&(t=f)}}return t}a=a||0;for(var l=e.length;l>0&&e[l-1][2]>a;l--)e[l]=e[l-1];e[l]=[o,n,a]}})(),r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},(()=>{var e,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;r.t=function(o,n){if(1&n&&(o=this(o)),8&n)return o;if("object"===typeof o&&o){if(4&n&&o.__esModule)return o;if(16&n&&"function"===typeof o.then)return o}var a=Object.create(null);r.r(a);var i={};e=e||[null,t({}),t([]),t(t)];for(var d=2&n&&o;("object"==typeof d||"function"==typeof d)&&!~e.indexOf(d);d=t(d))Object.getOwnPropertyNames(d).forEach(e=>i[e]=()=>o[e]);return i.default=()=>o,r.d(a,i),a}})(),r.d=(e,t)=>{for(var o in t)r.o(t,o)&&!r.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((t,o)=>(r.f[o](e,t),t),[])),r.u=e=>"static/js/"+e+"."+{118:"8a550f36",154:"a93817c6",158:"c7e50479",266:"e18a46b8",334:"0d196877",339:"c1ec8d08",452:"bad3d00e",453:"d9749a7d",469:"ec731235",501:"0b99fbb0",548:"da462cb8",558:"0464ebe3",579:"f8a21d69",620:"edc51951",771:"2b2378c2",791:"2cae987d",798:"21001033",910:"bec7c150"}[e]+".chunk.js",r.miniCssF=e=>{},r.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"===typeof window)return window}}(),r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={},t="frontend:";r.l=(o,n,a,i)=>{if(e[o])e[o].push(n);else{var d,c;if(void 0!==a)for(var f=document.getElementsByTagName("script"),l=0;l<f.length;l++){var u=f[l];if(u.getAttribute("src")==o||u.getAttribute("data-webpack")==t+a){d=u;break}}d||(c=!0,(d=document.createElement("script")).charset="utf-8",d.timeout=120,r.nc&&d.setAttribute("nonce",r.nc),d.setAttribute("data-webpack",t+a),d.src=o),e[o]=[n];var s=(t,r)=>{d.onerror=d.onload=null,clearTimeout(p);var n=e[o];if(delete e[o],d.parentNode&&d.parentNode.removeChild(d),n&&n.forEach(e=>e(r)),t)return t(r)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:d}),12e4);d.onerror=s.bind(null,d.onerror),d.onload=s.bind(null,d.onload),c&&document.head.appendChild(d)}}})(),r.r=e=>{"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),r.p="/",(()=>{var e={121:0};r.f.j=(t,o)=>{var n=r.o(e,t)?e[t]:void 0;if(0!==n)if(n)o.push(n[2]);else if(121!=t){var a=new Promise((r,o)=>n=e[t]=[r,o]);o.push(n[2]=a);var i=r.p+r.u(t),d=new Error;r.l(i,o=>{if(r.o(e,t)&&(0!==(n=e[t])&&(e[t]=void 0),n)){var a=o&&("load"===o.type?"missing":o.type),i=o&&o.target&&o.target.src;d.message="Loading chunk "+t+" failed.\n("+a+": "+i+")",d.name="ChunkLoadError",d.type=a,d.request=i,n[1](d)}},"chunk-"+t,t)}else e[t]=0},r.O.j=t=>0===e[t];var t=(t,o)=>{var n,a,i=o[0],d=o[1],c=o[2],f=0;if(i.some(t=>0!==e[t])){for(n in d)r.o(d,n)&&(r.m[n]=d[n]);if(c)var l=c(r)}for(t&&t(o);f<i.length;f++)a=i[f],r.o(e,a)&&e[a]&&e[a][0](),e[a]=0;return r.O(l)},o=self.webpackChunkfrontend=self.webpackChunkfrontend||[];o.forEach(t.bind(null,0)),o.push=t.bind(null,o.push.bind(o))})(),r.nc=void 0})();
|
||||
//# sourceMappingURL=runtime.0b5f0839.js.map
|
||||
@@ -10,6 +10,7 @@
|
||||
"test": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hello-pangea/dnd": "^18.0.1",
|
||||
"@chakra-ui/icons": "^2.1.1",
|
||||
"@chakra-ui/react": "^2.8.2",
|
||||
"@emotion/react": "^11.11.1",
|
||||
@@ -17,7 +18,7 @@
|
||||
"@hookform/resolvers": "^3.3.4",
|
||||
"@lobehub/icons": "^1.10.1",
|
||||
"@monaco-editor/react": "^4.6.0",
|
||||
"@tanstack/react-query": "^4.36.1",
|
||||
"@tanstack/react-query": "^4.43.0",
|
||||
"@testing-library/jest-dom": "^5.17.0",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
@@ -29,56 +30,58 @@
|
||||
"@types/react-dom": "^18.2.18",
|
||||
"@types/react-frame-component": "^4.1.6",
|
||||
"axios": "^1.13.6",
|
||||
"chart.js": "^4.4.1",
|
||||
"chart.js": "^4.5.1",
|
||||
"date-fns": "^4.1.0",
|
||||
"dompurify": "^3.3.0",
|
||||
"framer-motion": "^10.16.4",
|
||||
"i18next": "^23.7.16",
|
||||
"i18next-browser-languagedetector": "^7.2.0",
|
||||
"i18next-http-backend": "^2.4.2",
|
||||
"i18next": "^23.16.8",
|
||||
"i18next-browser-languagedetector": "^7.2.2",
|
||||
"i18next-http-backend": "^2.7.3",
|
||||
"lucide-react": "^0.379.0",
|
||||
"maplibre-gl": "^5.9.0",
|
||||
"maplibre-gl": "^5.20.1",
|
||||
"monaco-editor": "^0.49.0",
|
||||
"popmotion": "^11.0.5",
|
||||
"qrcode": "^1.5.4",
|
||||
"quill": "^2.0.3",
|
||||
"react": "^18.2.0",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-chartjs-2": "^5.2.0",
|
||||
"react-datepicker": "^8.7.0",
|
||||
"react-chartjs-2": "^5.3.1",
|
||||
"react-datepicker": "^8.10.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-frame-component": "^5.2.7",
|
||||
"react-helmet-async": "^2.0.5",
|
||||
"react-hook-form": "^7.48.2",
|
||||
"react-hook-form": "^7.71.2",
|
||||
"react-i18next": "^13.5.0",
|
||||
"react-icons": "^4.12.0",
|
||||
"react-icons": "^5.6.0",
|
||||
"react-image-crop": "^11.0.10",
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-quill": "^2.0.0",
|
||||
"react-router-dom": "^6.30.2",
|
||||
"react-router-dom": "^6.30.3",
|
||||
"react-simple-maps": "^3.0.0",
|
||||
"react-syntax-highlighter": "^15.6.6",
|
||||
"tinymce": "^8.2.2",
|
||||
"react-syntax-highlighter": "^16.1.1",
|
||||
"tinymce": "^8.3.2",
|
||||
"typescript": "^4.9.5",
|
||||
"web-vitals": "^2.1.4",
|
||||
"yup": "^1.3.3"
|
||||
"yup": "^1.7.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chart.js": "^2.9.41",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/geojson": "^7946.0.8",
|
||||
"@types/maplibre-gl": "^1.13.2",
|
||||
"@types/react-beautiful-dnd": "^13.1.8",
|
||||
"@types/react-chartjs-2": "^2.0.2",
|
||||
"@types/react-image-crop": "^8.1.6",
|
||||
"@types/react-syntax-highlighter": "^15.5.13",
|
||||
"@vitejs/plugin-react": "^4.4.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"jsdom": "^26.1.0",
|
||||
"vite": "^6.3.5",
|
||||
"vitest": "^3.1.1"
|
||||
},
|
||||
"overrides": {
|
||||
"flatted": "3.4.1",
|
||||
"glob@7": {
|
||||
"minimatch": "3.1.3"
|
||||
}
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 9.4 KiB |
@@ -1 +1,26 @@
|
||||
{"short_name": "Fotbal Club", "name": "Fotbal Club - Oficiální aplikace", "description": "Oficiální webové stránky fotbalového klubu - aktuality, zápasy, tabulky, hráči a fotogalerie", "icons": [{"src": "favicon.ico", "sizes": "64x64 32x32 24x24 16x16", "type": "image/x-icon"}, {"src": "logo192.png", "type": "image/png", "sizes": "192x192"}, {"src": "logo512.png", "type": "image/png", "sizes": "512x512"}], "start_url": ".", "display": "standalone", "theme_color": "#000000", "background_color": "#ffffff"}
|
||||
{
|
||||
"short_name": "Fotbal Club",
|
||||
"name": "Fotbal Club - Oficiální aplikace",
|
||||
"description": "Oficiální webové stránky fotbalového klubu - aktuality, zápasy, tabulky, hráči a fotogalerie",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png?v=2",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png?v=2",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
// Service Worker for PWA support and offline functionality
|
||||
|
||||
const CACHE_VERSION = 'v1.0.2';
|
||||
const CACHE_VERSION = 'v1.0.3';
|
||||
const CACHE_NAME = `fotbal-club-cache-${CACHE_VERSION}`;
|
||||
|
||||
// Rate limiting for background updates
|
||||
@@ -14,8 +14,8 @@ const STATIC_ASSETS = [
|
||||
'/index.html',
|
||||
'/manifest.json',
|
||||
'/favicon.ico',
|
||||
'/logo192.png',
|
||||
'/logo512.png',
|
||||
'/logo192.png?v=2',
|
||||
'/logo512.png?v=2',
|
||||
'/robots.txt',
|
||||
];
|
||||
|
||||
@@ -266,8 +266,8 @@ self.addEventListener('push', (event) => {
|
||||
const title = data.title || 'Fotbal Club';
|
||||
const options = {
|
||||
body: data.body || 'Nová notifikace',
|
||||
icon: '/logo192.png',
|
||||
badge: '/logo192.png',
|
||||
icon: '/logo192.png?v=2',
|
||||
badge: '/logo192.png?v=2',
|
||||
data: data.url || '/',
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,33 @@
|
||||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { vi } from 'vitest';
|
||||
import { HelmetProvider } from 'react-helmet-async';
|
||||
import App from './App';
|
||||
|
||||
test('renders learn react link', () => {
|
||||
render(<App />);
|
||||
const linkElement = screen.getByText(/learn react/i);
|
||||
expect(linkElement).toBeInTheDocument();
|
||||
vi.mock('./hooks/useUmami', () => ({
|
||||
useUmami: () => ({ isEnabled: false, isLoaded: false, trackEvent: vi.fn() }),
|
||||
}));
|
||||
|
||||
vi.mock('./hooks/usePublicSettings', () => ({
|
||||
usePublicSettings: () => ({ data: null }),
|
||||
}));
|
||||
|
||||
vi.mock('./utils/auth', () => ({
|
||||
isAuthenticated: () => false,
|
||||
checkAdminExists: async () => false,
|
||||
getToken: () => null,
|
||||
clearToken: vi.fn(),
|
||||
setToken: vi.fn(),
|
||||
}));
|
||||
|
||||
test('renders the app shell', () => {
|
||||
window.history.pushState({}, 'Test 404', '/test-not-found');
|
||||
|
||||
render(
|
||||
<HelmetProvider>
|
||||
<App />
|
||||
</HelmetProvider>
|
||||
);
|
||||
|
||||
expect(screen.getByText(/stránka nenalezena/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -13,6 +13,7 @@ interface UseFacrApiReturn {
|
||||
searchResults: SearchResponse['results'] | [];
|
||||
searchLoading: boolean;
|
||||
searchError: Error | null;
|
||||
clearSearchResults: () => void;
|
||||
|
||||
// Get club details by ID and type
|
||||
getClub: (clubId: string, clubType?: 'football' | 'futsal') => Promise<ClubInfo>;
|
||||
@@ -64,6 +65,7 @@ export const useFacrApi = (): UseFacrApiReturn => {
|
||||
async (query: string): Promise<SearchResponse> => {
|
||||
setSearchLoading(true);
|
||||
setSearchError(null);
|
||||
setSearchResults([]);
|
||||
try {
|
||||
const response = await handleApiCall(() => facrApi.searchClubs(query));
|
||||
setSearchResults(response.results || []);
|
||||
@@ -107,11 +109,18 @@ export const useFacrApi = (): UseFacrApiReturn => {
|
||||
facrApi.clearCache();
|
||||
}, []);
|
||||
|
||||
const clearSearchResults = useCallback(() => {
|
||||
setSearchResults([]);
|
||||
setSearchError(null);
|
||||
setSearchLoading(false);
|
||||
}, []);
|
||||
|
||||
return {
|
||||
searchClubs,
|
||||
searchResults,
|
||||
searchLoading,
|
||||
searchError,
|
||||
clearSearchResults,
|
||||
getClub,
|
||||
getClubTable,
|
||||
getClubCompetitions,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useState, useMemo, startTransition } from 'react';
|
||||
import { useEffect, useState, useMemo, useRef, startTransition } from 'react';
|
||||
import { Box, Button, FormControl, FormLabel, Input, VStack, Heading, useToast, SimpleGrid, Divider, Text, useColorModeValue, InputGroup, InputRightElement, List, ListItem, Spinner, HStack, Image, Checkbox, Tooltip, Alert, AlertIcon, Select, FormHelperText, Badge, Link } from '@chakra-ui/react';
|
||||
import { InfoOutlineIcon } from '@chakra-ui/icons';
|
||||
import './styles/MagazineHome.css';
|
||||
@@ -62,9 +62,11 @@ const SetupPage: React.FC = () => {
|
||||
const [clubUrl, setClubUrl] = useState('');
|
||||
const [clubLink, setClubLink] = useState('');
|
||||
const [clubQuery, setClubQuery] = useState('');
|
||||
const [selectedClubSearchLabel, setSelectedClubSearchLabel] = useState('');
|
||||
const { data: publicSettings } = usePublicSettings();
|
||||
const isManualClubDataMode = (publicSettings?.club_data_mode || '').toLowerCase() === 'manual';
|
||||
const { searchClubs, searchResults, searchLoading } = useFacrApi();
|
||||
const { searchClubs, searchResults, searchLoading, clearSearchResults } = useFacrApi();
|
||||
const suppressNextClubSearchRef = useRef(false);
|
||||
|
||||
const resolveLogoUrl = (u?: string | null) => {
|
||||
if (!u) return undefined;
|
||||
@@ -216,11 +218,16 @@ const SetupPage: React.FC = () => {
|
||||
useEffect(() => {
|
||||
const q = clubQuery.trim();
|
||||
if (!q) return;
|
||||
if (selectedClubSearchLabel.trim() && q === selectedClubSearchLabel.trim()) return;
|
||||
if (suppressNextClubSearchRef.current) {
|
||||
suppressNextClubSearchRef.current = false;
|
||||
return;
|
||||
}
|
||||
const t = setTimeout(() => {
|
||||
searchClubs(q).catch(() => {});
|
||||
}, 300);
|
||||
return () => clearTimeout(t);
|
||||
}, [clubQuery, searchClubs]);
|
||||
}, [clubQuery, searchClubs, selectedClubSearchLabel]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDomainHost && !showAdvancedApi) {
|
||||
@@ -332,12 +339,15 @@ const SetupPage: React.FC = () => {
|
||||
};
|
||||
|
||||
const handleSelectClub = async (item: SearchResult) => {
|
||||
suppressNextClubSearchRef.current = true;
|
||||
setSelectedClubSearchLabel(item.name || '');
|
||||
clearSearchResults();
|
||||
const clubIdValue = item.club_id || '';
|
||||
setClubId(clubIdValue);
|
||||
setClubType(item.club_type || 'football');
|
||||
setClubName(item.name || '');
|
||||
setClubUrl(item.url || '');
|
||||
setClubQuery(item.name || '');
|
||||
setClubQuery('');
|
||||
|
||||
// Try to fetch both logo and club name from logoapi first
|
||||
let logoUrl = '';
|
||||
@@ -827,12 +837,20 @@ const SetupPage: React.FC = () => {
|
||||
<FormControl>
|
||||
<FormLabel>Hledat klub (FAČR)</FormLabel>
|
||||
<InputGroup>
|
||||
<Input value={clubQuery} onChange={(e) => setClubQuery(e.target.value)} placeholder="Hledejte podle názvu klubu" />
|
||||
<Input
|
||||
value={clubQuery}
|
||||
onChange={(e) => {
|
||||
suppressNextClubSearchRef.current = false;
|
||||
setSelectedClubSearchLabel('');
|
||||
setClubQuery(e.target.value);
|
||||
}}
|
||||
placeholder="Hledejte podle názvu klubu"
|
||||
/>
|
||||
<InputRightElement>
|
||||
{searchLoading ? <Spinner size="sm" /> : null}
|
||||
</InputRightElement>
|
||||
</InputGroup>
|
||||
{clubQuery && searchResults?.length > 0 && (
|
||||
{clubQuery.trim() && clubQuery.trim() !== selectedClubSearchLabel && searchResults?.length > 0 && (
|
||||
<Box mt={2} borderWidth="1px" borderRadius="md" maxH="240px" overflowY="auto">
|
||||
<List spacing={0}>
|
||||
{searchResults.filter((r) => r.name && r.name.trim() !== '').slice(0, 8).map((r) => (
|
||||
|
||||
@@ -47,7 +47,7 @@ import {
|
||||
Collapse,
|
||||
Icon,
|
||||
} from '@chakra-ui/react';
|
||||
import { DragDropContext, Droppable, Draggable, DropResult } from 'react-beautiful-dnd';
|
||||
import { DragDropContext, Droppable, Draggable, DropResult } from '@hello-pangea/dnd';
|
||||
import AdminLayout from '../../layouts/AdminLayout';
|
||||
import {
|
||||
AddIcon,
|
||||
|
||||
@@ -2,24 +2,17 @@ import axios, { AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from
|
||||
import { reportError } from './errorReporter';
|
||||
import { getToken } from '../utils/auth';
|
||||
import { logAction } from './actionLog';
|
||||
import { resolveApiBaseUrl } from '../utils/apiBaseUrl';
|
||||
|
||||
function readStored(key: string): string | null {
|
||||
try { return localStorage.getItem(key); } catch { return null; }
|
||||
try {
|
||||
return localStorage.getItem(key);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const storedApi = typeof window !== 'undefined' ? (readStored('fc_api_base_url') || readStored('api_base_url')) : null;
|
||||
const envApiUrl = process.env.REACT_APP_API_URL || process.env.REACT_APP_API_BASE_URL;
|
||||
let API_URL = storedApi || envApiUrl || '/api/v1';
|
||||
|
||||
try {
|
||||
const maybe = new URL(API_URL, typeof window !== 'undefined' ? window.location.origin : undefined);
|
||||
if (!/\/api\//.test(maybe.pathname)) {
|
||||
maybe.pathname = maybe.pathname.replace(/\/$/, '') + '/api/v1';
|
||||
API_URL = maybe.toString();
|
||||
} else {
|
||||
API_URL = maybe.toString();
|
||||
}
|
||||
} catch {}
|
||||
const API_URL = resolveApiBaseUrl();
|
||||
|
||||
export const api: AxiosInstance = axios.create({
|
||||
baseURL: API_URL,
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
function readStoredApiBase(key: string): string | null {
|
||||
try {
|
||||
return localStorage.getItem(key);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeApiBaseUrl(input?: string | null): string {
|
||||
const fallbackOrigin = typeof window !== 'undefined' ? window.location.origin : 'http://localhost';
|
||||
const candidate = (input || '').trim() || '/api/v1';
|
||||
|
||||
try {
|
||||
const resolved = new URL(candidate, fallbackOrigin);
|
||||
if (!/\/api\//.test(resolved.pathname)) {
|
||||
resolved.pathname = resolved.pathname.replace(/\/$/, '') + '/api/v1';
|
||||
}
|
||||
return resolved.toString();
|
||||
} catch {
|
||||
const trimmed = candidate.replace(/\/$/, '');
|
||||
return /\/api\//.test(trimmed) ? trimmed : `${trimmed}/api/v1`;
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveApiBaseUrl(): string {
|
||||
const storedApi =
|
||||
typeof window !== 'undefined'
|
||||
? readStoredApiBase('fc_api_base_url') || readStoredApiBase('api_base_url')
|
||||
: null;
|
||||
const envApiUrl = process.env.REACT_APP_API_URL || process.env.REACT_APP_API_BASE_URL;
|
||||
|
||||
return normalizeApiBaseUrl(storedApi || envApiUrl || '/api/v1');
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
// Use a single canonical key for the auth token across the app
|
||||
// Many modules expect 'auth_token' (see usages in services and build artifacts).
|
||||
import { resolveApiBaseUrl } from './apiBaseUrl';
|
||||
|
||||
const TOKEN_KEY = 'auth_token';
|
||||
const HAS_ADMIN_KEY = 'fotbal_club_has_admin';
|
||||
|
||||
@@ -43,9 +45,8 @@ export const setHasAdmin = (value: boolean): void => {
|
||||
|
||||
export const checkAdminExists = async (): Promise<boolean> => {
|
||||
try {
|
||||
// Use shared API base URL which is normalized to '/api/v1'
|
||||
const { API_URL } = await import('../services/api');
|
||||
const response = await fetch(`${API_URL}/auth/admin/exists`, {
|
||||
const apiUrl = resolveApiBaseUrl();
|
||||
const response = await fetch(`${apiUrl}/auth/admin/exists`, {
|
||||
headers: { 'Accept': 'application/json' },
|
||||
});
|
||||
if (response.ok) {
|
||||
|
||||
@@ -78,7 +78,7 @@ export function parseGoogleMapsUrl(url: string): MapCoordinates | null {
|
||||
}
|
||||
|
||||
// Try to extract from pathname (/@lat,lng,zoom format)
|
||||
const pathMatch = urlObj.pathname.match(/@(-?\d+\.\d+),(-?\d+\.\d+),(\d+)z/);
|
||||
const pathMatch = urlObj.pathname.match(/@(-?\d+\.\d+),(-?\d+\.\d+),(\d+)(?:[mz])/);
|
||||
if (pathMatch) {
|
||||
const latitude = parseFloat(pathMatch[1]);
|
||||
const longitude = parseFloat(pathMatch[2]);
|
||||
|
||||
@@ -253,6 +253,29 @@ const recordCircuitBreakerSuccess = (): void => {
|
||||
}
|
||||
};
|
||||
|
||||
const LOGO_API_HOSTS = new Set([
|
||||
'logoapi.sportcreative.eu',
|
||||
'www.logoapi.sportcreative.eu',
|
||||
]);
|
||||
|
||||
const normalizeLogoApiUrl = (raw?: string | null): string | null => {
|
||||
const value = String(raw || '').trim();
|
||||
if (!value) return null;
|
||||
|
||||
try {
|
||||
const fallbackOrigin = typeof window !== 'undefined'
|
||||
? window.location.origin
|
||||
: 'https://logoapi.sportcreative.eu';
|
||||
const parsed = new URL(value, fallbackOrigin);
|
||||
if (LOGO_API_HOSTS.has(parsed.hostname)) {
|
||||
parsed.protocol = 'https:';
|
||||
}
|
||||
return parsed.toString();
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetch logo from logoapi.sportcreative.eu with optimization and circuit breaker
|
||||
*/
|
||||
@@ -267,8 +290,16 @@ export const fetchLogoFromLogoAPI = async (teamId: string, teamName?: string): P
|
||||
// Check cache first
|
||||
const cached = await getCachedLogo(teamId);
|
||||
if (cached?.url && !cached.url.startsWith('blob:')) {
|
||||
const normalizedCachedUrl = normalizeLogoApiUrl(cached.url);
|
||||
await updateLastUsed(teamId);
|
||||
return cached.url;
|
||||
if (normalizedCachedUrl && normalizedCachedUrl !== cached.url) {
|
||||
await saveCachedLogo({
|
||||
...cached,
|
||||
url: normalizedCachedUrl,
|
||||
lastUsed: Date.now(),
|
||||
});
|
||||
}
|
||||
return normalizedCachedUrl;
|
||||
}
|
||||
|
||||
// Fetch from logoapi with timeout
|
||||
@@ -289,7 +320,7 @@ export const fetchLogoFromLogoAPI = async (teamId: string, teamName?: string): P
|
||||
}
|
||||
|
||||
const data = await res.json();
|
||||
const url = data.logo_url_svg || data.logo_url_png || data.logo_url;
|
||||
const url = normalizeLogoApiUrl(data.logo_url_svg || data.logo_url_png || data.logo_url);
|
||||
|
||||
if (!url) {
|
||||
recordCircuitBreakerFailure();
|
||||
@@ -319,19 +350,38 @@ export const fetchLogoFromLogoAPI = async (teamId: string, teamName?: string): P
|
||||
*/
|
||||
export const fetchClubNameAndLogoFromAPI = async (teamId: string): Promise<{ clubName?: string; logoUrl?: string } | null> => {
|
||||
try {
|
||||
// Fetch from logoapi
|
||||
const res = await fetch(`https://logoapi.sportcreative.eu/logos/${teamId}/json`, {
|
||||
method: 'GET',
|
||||
headers: { 'Accept': 'application/json' },
|
||||
});
|
||||
const cached = await getCachedLogo(teamId);
|
||||
const cachedLogoUrl = cached?.url && !cached.url.startsWith('blob:')
|
||||
? normalizeLogoApiUrl(cached.url)
|
||||
: null;
|
||||
|
||||
if (!res.ok) return null;
|
||||
// Fetch from logoapi
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
||||
let res: Response;
|
||||
try {
|
||||
res = await fetch(`https://logoapi.sportcreative.eu/logos/${teamId}/json`, {
|
||||
method: 'GET',
|
||||
headers: { 'Accept': 'application/json' },
|
||||
signal: controller.signal,
|
||||
});
|
||||
} finally {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
|
||||
if (!res.ok) {
|
||||
recordCircuitBreakerFailure();
|
||||
return cachedLogoUrl ? { logoUrl: cachedLogoUrl } : null;
|
||||
}
|
||||
|
||||
const data = await res.json();
|
||||
const logoUrl = data.logo_url_svg || data.logo_url_png || data.logo_url;
|
||||
const logoUrl = normalizeLogoApiUrl(data.logo_url_svg || data.logo_url_png || data.logo_url);
|
||||
const clubName = data.club_name;
|
||||
|
||||
if (!logoUrl && !clubName) return null;
|
||||
if (!logoUrl && !clubName) {
|
||||
recordCircuitBreakerFailure();
|
||||
return cachedLogoUrl ? { logoUrl: cachedLogoUrl } : null;
|
||||
}
|
||||
|
||||
// Cache the logo if available
|
||||
if (logoUrl) {
|
||||
@@ -344,13 +394,20 @@ export const fetchClubNameAndLogoFromAPI = async (teamId: string): Promise<{ clu
|
||||
});
|
||||
}
|
||||
|
||||
recordCircuitBreakerSuccess();
|
||||
|
||||
return {
|
||||
clubName: clubName || undefined,
|
||||
logoUrl: logoUrl || undefined,
|
||||
logoUrl: logoUrl || cachedLogoUrl || undefined,
|
||||
};
|
||||
} catch (e) {
|
||||
recordCircuitBreakerFailure();
|
||||
console.warn(`Failed to fetch club info for team ${teamId}:`, e);
|
||||
return null;
|
||||
const cached = await getCachedLogo(teamId).catch(() => null);
|
||||
const cachedLogoUrl = cached?.url && !cached.url.startsWith('blob:')
|
||||
? normalizeLogoApiUrl(cached.url)
|
||||
: null;
|
||||
return cachedLogoUrl ? { logoUrl: cachedLogoUrl } : null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"@types/geojson": "^7946.0.16"
|
||||
},
|
||||
"dependencies": {
|
||||
"@openapi-mcp/server": "^0.0.1",
|
||||
"quill-image-resize-module-v2": "^3.0.0",
|
||||
"react-markdown": "^10.1.0",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
"name": "fotbal-club-root",
|
||||
"private": true
|
||||
}
|
||||
|
||||