From 6b5b513d97824595a3ed2ee54a4813a35f57cb7d Mon Sep 17 00:00:00 2001 From: Stoynov Date: Thu, 30 Apr 2026 12:47:24 +0300 Subject: [PATCH 01/13] Add language support --- frontend/src/assets/translate/bg.json | 5 +++++ frontend/src/assets/translate/en.json | 5 +++++ frontend/src/config/i18n.ts | 23 +++++++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 frontend/src/assets/translate/bg.json create mode 100644 frontend/src/assets/translate/en.json create mode 100644 frontend/src/config/i18n.ts diff --git a/frontend/src/assets/translate/bg.json b/frontend/src/assets/translate/bg.json new file mode 100644 index 0000000..d7d32e3 --- /dev/null +++ b/frontend/src/assets/translate/bg.json @@ -0,0 +1,5 @@ +{ + "welcome": "Здравейте", + "admin": "Админ", + "logout": "Logout" +} \ No newline at end of file diff --git a/frontend/src/assets/translate/en.json b/frontend/src/assets/translate/en.json new file mode 100644 index 0000000..556df70 --- /dev/null +++ b/frontend/src/assets/translate/en.json @@ -0,0 +1,5 @@ +{ + "welcome": "Welcome", + "admin": "Admin", + "logout": "Logout" +} \ No newline at end of file diff --git a/frontend/src/config/i18n.ts b/frontend/src/config/i18n.ts new file mode 100644 index 0000000..cad9487 --- /dev/null +++ b/frontend/src/config/i18n.ts @@ -0,0 +1,23 @@ +import i18n from 'i18next'; +import {initReactI18next} from 'react-i18next'; +import en from "../assets/translate/en.json" +import bg from '../assets/translate/bg.json'; +import * as Localization from 'expo-localization'; + +const deviceLanguage = Localization.getLocales()[0].languageCode; + +i18n + .use(initReactI18next) + .init({ + resources: { + en: {translation: en}, + bg: {translation: bg}, + }, + lng: deviceLanguage === 'bg' ? 'bg' : 'en', + fallbackLng: 'en', + interpolation: { + escapeValue: false, + } + }); + +export default i18n; \ No newline at end of file From 03fd09844ed9ed63ecbe219e3c1d5082c873577a Mon Sep 17 00:00:00 2001 From: Stoynov Date: Thu, 30 Apr 2026 12:47:48 +0300 Subject: [PATCH 02/13] Add theme support --- frontend/src/constants/theme.tsx | 117 +++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 frontend/src/constants/theme.tsx diff --git a/frontend/src/constants/theme.tsx b/frontend/src/constants/theme.tsx new file mode 100644 index 0000000..f23540b --- /dev/null +++ b/frontend/src/constants/theme.tsx @@ -0,0 +1,117 @@ +export const theme = { + colors: { + primary: '#444444', + secondary: '#CECECC', + background: '#F8F9FA', + surface: '#FFFFFF', + textPrimary: '#333333', + textSecondary: '#777777', + border: '#e0e0e0', + ripple: 'rgba(0,0,0,0.1)', + shadow: '#000', + transparent: 'transparent', + textTertiary: '#555555', + textValidationError: '#E3525E', + error: '#F26161' + }, + spacing: { + none: 0, + xs: 4, + sm: 8, + md: 16, + lg: 24, + xl: 32, + }, + fontSizes: { + body: 14, + title: 18, + header: 24, + subheader: 12, + }, + radii: { + sm: 4, + md: 8, + lg: 16, + full: 999, + }, + sizes: { + priceText: 16, + cardPadding: 12, + cardMargin: 8, + addButtonSize: 30, + + profileImage: 40, + tabBarHeight: 60, + imageHeight: 240, + icon: 24, + addButton: 30, + maxWidth: 400 + }, + iconSizes: { + md: 24, + }, + elevation: { + sm: 2, + md: 4, + lg: 8, + }, + lineHeights: { + body: 18, + title: 22, + }, + components: { + header: { + paddingHorizontal: 16, + paddingVertical: 12, + height: 64, + imageSize: 40, + }, + card: { + padding: 16, + margin: 8, + borderRadius: 8, + imageHeight: 240, + }, + button: { + sm: { + padding: 8, + borderRadius: 4, + }, + md: { + padding: 12, + borderRadius: 8, + } + }, + tabBar: { + iconSize: 24, + labelMargin: 4, + }, + listItem: { + imageSize: 80, + paddingVertical: 12, + }, + cardImage: { + height: 240, + borderRadius: 8, + }, + login: { + containerWidth: 340, + containerHeight: 400, + inputWidth: 300, + buttonWidth: 140, + logoSize: 100, + borderRadius: 20, + overlay: 'rgba(142,129,129,0.4)' + }, + testButton: { + width: 117, + height: 40, + borderWidth: 2.5 + }, + cafeDetail: { + imageHeight: 200, + }, + } +}; + +export default theme; \ No newline at end of file From 780e8c242cf90fde60401fb311677571a3e5ef62 Mon Sep 17 00:00:00 2001 From: Stoynov Date: Thu, 30 Apr 2026 12:48:10 +0300 Subject: [PATCH 03/13] Dependencies --- frontend/package-lock.json | 647 ++++++++++++++++++++++++++++++++++++- frontend/package.json | 9 + 2 files changed, 645 insertions(+), 11 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 9acebbd..fcd5a56 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,15 +8,24 @@ "name": "frontend-temp", "version": "1.0.0", "dependencies": { + "@expo/vector-icons": "^15.1.1", + "@react-navigation/native": "^7.2.2", + "@react-navigation/native-stack": "^7.14.12", "expo": "~54.0.33", + "expo-localization": "^55.0.13", "expo-status-bar": "~3.0.9", + "i18next": "^26.0.8", "react": "19.1.0", "react-dom": "^19.1.0", + "react-i18next": "^17.0.6", "react-native": "0.81.5", + "react-native-safe-area-context": "^5.7.0", + "react-native-screens": "^4.24.0", "react-native-web": "^0.21.2" }, "devDependencies": { "@types/react": "~19.1.0", + "babel-plugin-module-resolver": "^5.0.3", "typescript": "~5.9.2" } }, @@ -2404,6 +2413,17 @@ "integrity": "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==", "license": "MIT" }, + "node_modules/@expo/vector-icons": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-15.1.1.tgz", + "integrity": "sha512-Iu2VkcoI5vygbtYngm7jb4ifxElNVXQYdDrYkT7UCEIiKLeWnQY0wf2ZhHZ+Wro6Sc5TaumpKUOqDRpLi5rkvw==", + "license": "MIT", + "peerDependencies": { + "expo-font": ">=14.0.4", + "react": "*", + "react-native": "*" + } + }, "node_modules/@expo/ws-tunnel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@expo/ws-tunnel/-/ws-tunnel-1.0.6.tgz", @@ -3135,6 +3155,123 @@ "integrity": "sha512-0HuJ8YtqlTVRXGZuGeBejLE04wSQsibpTI+RGOyVqxZvgtlLLC/Ssw0UmbHhT4lYMp2fhdtvKZSs5emWB1zR/g==", "license": "MIT" }, + "node_modules/@react-navigation/core": { + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-7.17.2.tgz", + "integrity": "sha512-Rt2OZwcgOmjv401uLGAKaRM6xo0fiBce/A7LfRHI1oe5FV+KooWcgAoZ2XOtgKj6UzVMuQWt3b2e6rxo/mDJRA==", + "license": "MIT", + "dependencies": { + "@react-navigation/routers": "^7.5.3", + "escape-string-regexp": "^4.0.0", + "fast-deep-equal": "^3.1.3", + "nanoid": "^3.3.11", + "query-string": "^7.1.3", + "react-is": "^19.1.0", + "use-latest-callback": "^0.2.4", + "use-sync-external-store": "^1.5.0" + }, + "peerDependencies": { + "react": ">= 18.2.0" + } + }, + "node_modules/@react-navigation/core/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-navigation/core/node_modules/react-is": { + "version": "19.2.5", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.5.tgz", + "integrity": "sha512-Dn0t8IQhCmeIT3wu+Apm1/YVsJXsGWi6k4sPdnBIdqMVtHtv0IGi6dcpNpNkNac0zB2uUAqNX3MHzN8c+z2rwQ==", + "license": "MIT" + }, + "node_modules/@react-navigation/elements": { + "version": "2.9.15", + "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-2.9.15.tgz", + "integrity": "sha512-cyz/pPiyyC6gaTVLsGFc1g0MYgrmuCFqklAWGXMWPscr5YU3ui94vPI4vnZwcsEy0T758TQWLzmS5XudZeRKcA==", + "license": "MIT", + "dependencies": { + "color": "^4.2.3", + "use-latest-callback": "^0.2.4", + "use-sync-external-store": "^1.5.0" + }, + "peerDependencies": { + "@react-native-masked-view/masked-view": ">= 0.2.0", + "@react-navigation/native": "^7.2.2", + "react": ">= 18.2.0", + "react-native": "*", + "react-native-safe-area-context": ">= 4.0.0" + }, + "peerDependenciesMeta": { + "@react-native-masked-view/masked-view": { + "optional": true + } + } + }, + "node_modules/@react-navigation/native": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.2.2.tgz", + "integrity": "sha512-kem1Ko2BcbAjmbQIv66dNmr6EtfDut3QU0qjsVhMnLLhktwyXb6FzZYp8gTrUb6AvkAbaJoi+BF5Pl55pAUa5w==", + "license": "MIT", + "dependencies": { + "@react-navigation/core": "^7.17.2", + "escape-string-regexp": "^4.0.0", + "fast-deep-equal": "^3.1.3", + "nanoid": "^3.3.11", + "use-latest-callback": "^0.2.4" + }, + "peerDependencies": { + "react": ">= 18.2.0", + "react-native": "*" + } + }, + "node_modules/@react-navigation/native-stack": { + "version": "7.14.12", + "resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-7.14.12.tgz", + "integrity": "sha512-dUfpkrVeVKKV8iqXsmoUp3Rv0iH3YaB3eZwScru/FlcqAp/r3/qA6zEXkGX9hZK+/ziWAPFrf1frBSNbgOYSFQ==", + "license": "MIT", + "dependencies": { + "@react-navigation/elements": "^2.9.15", + "color": "^4.2.3", + "sf-symbols-typescript": "^2.1.0", + "warn-once": "^0.1.1" + }, + "peerDependencies": { + "@react-navigation/native": "^7.2.2", + "react": ">= 18.2.0", + "react-native": "*", + "react-native-safe-area-context": ">= 4.0.0", + "react-native-screens": ">= 4.0.0" + } + }, + "node_modules/@react-navigation/native/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-navigation/routers": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-7.5.3.tgz", + "integrity": "sha512-1tJHg4KKRJuQ1/EvJxatrMef3NZXEPzwUIUZ3n1yJ2t7Q97siwRtbynRpQG9/69ebbtiZ8W3ScOZF/OmhvM4Rg==", + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.10", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", @@ -3579,6 +3716,117 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/babel-plugin-module-resolver": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.3.tgz", + "integrity": "sha512-h8h6H71ZvdLJZxZrYkaeR30BojTaV7O9GfqacY14SNj5CNB8ocL9tydNzTC0JrnNN7vY3eJhwCmkDj7tuEUaqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-babel-config": "^2.1.1", + "glob": "^9.3.3", + "pkg-up": "^3.1.0", + "reselect": "^4.1.7", + "resolve": "^1.22.8" + } + }, + "node_modules/babel-plugin-module-resolver/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/babel-plugin-module-resolver/node_modules/brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/babel-plugin-module-resolver/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/babel-plugin-module-resolver/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/babel-plugin-module-resolver/node_modules/minimatch": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.7.tgz", + "integrity": "sha512-V+1uQNdzybxa14e/p00HZnQNNcTjnRJjDxg2V8wtkjFctq4M7hXFws4oekyTP0Jebeq7QYtpFyOeBAjc88zvYg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/babel-plugin-module-resolver/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-module-resolver/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/babel-plugin-module-resolver/node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.17", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", @@ -4086,6 +4334,19 @@ "node": ">=0.8" } }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -4101,6 +4362,34 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "license": "MIT" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, "node_modules/commander": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", @@ -4275,6 +4564,15 @@ } } }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -4559,6 +4857,34 @@ "react-native": "*" } }, + "node_modules/expo-font": { + "version": "55.0.6", + "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-55.0.6.tgz", + "integrity": "sha512-x9czUA3UQWjIwa0ZUEs/eWJNqB4mAue/m4ltESlNPLZhHL0nWWqIfsyHmklTLFH7mVfcHSJvew6k+pR2FE1zVw==", + "license": "MIT", + "peer": true, + "dependencies": { + "fontfaceobserver": "^2.1.0" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, + "node_modules/expo-localization": { + "version": "55.0.13", + "resolved": "https://registry.npmjs.org/expo-localization/-/expo-localization-55.0.13.tgz", + "integrity": "sha512-fXiEUUihIrXmAEzoneaTOFcQ7TKmr25RR/ymrB/MvYTVnmevFA1zY2KI0VSiXY+NKKjZ8mG65YSn1wh4gEYKxA==", + "license": "MIT", + "dependencies": { + "rtl-detect": "^1.0.2" + }, + "peerDependencies": { + "expo": "*", + "react": "*" + } + }, "node_modules/expo-modules-autolinking": { "version": "3.0.25", "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-3.0.25.tgz", @@ -4767,17 +5093,6 @@ } } }, - "node_modules/expo/node_modules/@expo/vector-icons": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-15.1.1.tgz", - "integrity": "sha512-Iu2VkcoI5vygbtYngm7jb4ifxElNVXQYdDrYkT7UCEIiKLeWnQY0wf2ZhHZ+Wro6Sc5TaumpKUOqDRpLi5rkvw==", - "license": "MIT", - "peerDependencies": { - "expo-font": ">=14.0.4", - "react": "*", - "react-native": "*" - } - }, "node_modules/expo/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -5009,6 +5324,12 @@ "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", "license": "Apache-2.0" }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -5066,6 +5387,15 @@ "node": ">=8" } }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/finalhandler": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", @@ -5099,6 +5429,16 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/find-babel-config": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-2.1.2.tgz", + "integrity": "sha512-ZfZp1rQyp4gyuxqt1ZqjFGVeVBvmpURMqdIWXbPRfB97Bf6BzdK/xSIbylEINzQ0kB5tlDQfn9HkNXXWsqTqLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.3" + } + }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -5284,6 +5624,15 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "license": "ISC" }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "license": "MIT", + "dependencies": { + "void-elements": "3.1.0" + } + }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", @@ -5332,6 +5681,34 @@ "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==", "license": "BSD-3-Clause" }, + "node_modules/i18next": { + "version": "26.0.8", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-26.0.8.tgz", + "integrity": "sha512-BRzLom0mhDhV9v0QhgUUHWQJuwFmnr1194xEcNLYD6ym8y8s542n4jXUvRLnhNTbh9PmpU6kGZamyuGHQMsGjw==", + "funding": [ + { + "type": "individual", + "url": "https://www.locize.com/i18next" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + }, + { + "type": "individual", + "url": "https://www.locize.com" + } + ], + "license": "MIT", + "peerDependencies": { + "typescript": "^5 || ^6" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -5426,6 +5803,12 @@ "loose-envify": "^1.0.0" } }, + "node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "license": "MIT" + }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", @@ -7250,6 +7633,85 @@ "node": ">= 6" } }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/plist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.1.tgz", @@ -7411,6 +7873,24 @@ "qrcode-terminal": "bin/qrcode-terminal.js" } }, + "node_modules/query-string": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", + "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "license": "MIT", + "dependencies": { + "decode-uri-component": "^0.2.2", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/queue": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", @@ -7475,6 +7955,45 @@ "react": "^19.1.0" } }, + "node_modules/react-freeze": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/react-freeze/-/react-freeze-1.0.4.tgz", + "integrity": "sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=17.0.0" + } + }, + "node_modules/react-i18next": { + "version": "17.0.6", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-17.0.6.tgz", + "integrity": "sha512-WzJ6SMKF+GTD7JZZqxSR1AKKmXjaSu39sClUrNlwxS4Tl7a99O+ltFy6yhPMO+wgZuxpQjJ2PZkfrQKmAqrLhw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2", + "html-parse-stringify": "^3.0.1", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "i18next": ">= 26.0.1", + "react": ">= 16.8.0", + "typescript": "^5 || ^6" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -7548,6 +8067,30 @@ "react-native": "*" } }, + "node_modules/react-native-safe-area-context": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.7.0.tgz", + "integrity": "sha512-/9/MtQz8ODphjsLdZ+GZAIcC/RtoqW9EeShf7Uvnfgm/pzYrJ75y3PV/J1wuAV1T5Dye5ygq4EAW20RoBq0ABQ==", + "license": "MIT", + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-screens": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.24.0.tgz", + "integrity": "sha512-SyoiGaDofiyGPFrUkn1oGsAzkRuX1JUvTD9YQQK3G1JGQ5VWkvHgYSsc1K9OrLsDQxN7NmV71O0sHCAh8cBetA==", + "license": "MIT", + "dependencies": { + "react-freeze": "^1.0.0", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native-web": { "version": "0.21.2", "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.21.2.tgz", @@ -7778,6 +8321,13 @@ "path-parse": "^1.0.5" } }, + "node_modules/reselect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==", + "dev": true, + "license": "MIT" + }, "node_modules/resolve": { "version": "1.22.12", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", @@ -7901,6 +8451,12 @@ "node": "*" } }, + "node_modules/rtl-detect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.1.2.tgz", + "integrity": "sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==", + "license": "BSD-3-Clause" + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -8062,6 +8618,15 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, + "node_modules/sf-symbols-typescript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/sf-symbols-typescript/-/sf-symbols-typescript-2.2.0.tgz", + "integrity": "sha512-TPbeg0b7ylrswdGCji8FRGFAKuqbpQlLbL8SOle3j1iHSs5Ob5mhvMAxWN2UItOjgALAB5Zp3fmMfj8mbWvXKw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -8112,6 +8677,15 @@ "plist": "^3.0.5" } }, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -8173,6 +8747,15 @@ "node": ">=0.10.0" } }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -8236,6 +8819,15 @@ "node": ">= 0.10.0" } }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -8763,6 +9355,24 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/use-latest-callback": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.2.6.tgz", + "integrity": "sha512-FvRG9i1HSo0wagmX63Vrm8SnlUU3LMM3WyZkQ76RnslpBrX694AdG4A0zQBx2B3ZifFA0yv/BaEHGBnEax5rZg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -8806,6 +9416,15 @@ "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==", "license": "MIT" }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -8815,6 +9434,12 @@ "makeerror": "1.0.12" } }, + "node_modules/warn-once": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz", + "integrity": "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==", + "license": "MIT" + }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 851feb0..f7ec601 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,15 +9,24 @@ "web": "expo start --web" }, "dependencies": { + "@expo/vector-icons": "^15.1.1", + "@react-navigation/native": "^7.2.2", + "@react-navigation/native-stack": "^7.14.12", "expo": "~54.0.33", + "expo-localization": "^55.0.13", "expo-status-bar": "~3.0.9", + "i18next": "^26.0.8", "react": "19.1.0", "react-dom": "^19.1.0", + "react-i18next": "^17.0.6", "react-native": "0.81.5", + "react-native-safe-area-context": "^5.7.0", + "react-native-screens": "^4.24.0", "react-native-web": "^0.21.2" }, "devDependencies": { "@types/react": "~19.1.0", + "babel-plugin-module-resolver": "^5.0.3", "typescript": "~5.9.2" }, "private": true From ccb11a0922791b338d80a459c423f58d346a0cbe Mon Sep 17 00:00:00 2001 From: Stoynov Date: Thu, 30 Apr 2026 12:48:20 +0300 Subject: [PATCH 04/13] Logout svg --- frontend/src/assets/images/logout-svgrepo-com.svg | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 frontend/src/assets/images/logout-svgrepo-com.svg diff --git a/frontend/src/assets/images/logout-svgrepo-com.svg b/frontend/src/assets/images/logout-svgrepo-com.svg new file mode 100644 index 0000000..bb35cf0 --- /dev/null +++ b/frontend/src/assets/images/logout-svgrepo-com.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file From 154856e71f3a332425dc1d43cfb81a9a9ddec35c Mon Sep 17 00:00:00 2001 From: Stoynov Date: Thu, 30 Apr 2026 12:48:34 +0300 Subject: [PATCH 05/13] Navigation support --- frontend/src/navigation/Navigation.tsx | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 frontend/src/navigation/Navigation.tsx diff --git a/frontend/src/navigation/Navigation.tsx b/frontend/src/navigation/Navigation.tsx new file mode 100644 index 0000000..d86727a --- /dev/null +++ b/frontend/src/navigation/Navigation.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import {createNativeStackNavigator} from '@react-navigation/native-stack'; + +import Home from '../screens/home/Home'; + +export type RootStackParamList = { + home: undefined; + login: undefined; + profile: { userId: number }; + test: undefined; +}; + +const Stack = createNativeStackNavigator(); + +const Navigation = () => { + return ( + + + + ); +}; + +export default Navigation; \ No newline at end of file From 6ca13f8a5e28bf841b41750ee8b9a707c6725fcc Mon Sep 17 00:00:00 2001 From: Stoynov Date: Thu, 30 Apr 2026 12:48:51 +0300 Subject: [PATCH 06/13] Add header --- .../src/components/header/Header.style.tsx | 56 +++++++++++++++++++ frontend/src/components/header/Header.tsx | 31 ++++++++++ 2 files changed, 87 insertions(+) create mode 100644 frontend/src/components/header/Header.style.tsx create mode 100644 frontend/src/components/header/Header.tsx diff --git a/frontend/src/components/header/Header.style.tsx b/frontend/src/components/header/Header.style.tsx new file mode 100644 index 0000000..efc149e --- /dev/null +++ b/frontend/src/components/header/Header.style.tsx @@ -0,0 +1,56 @@ +import { StyleSheet } from 'react-native'; +import { theme } from '../../constants/theme'; + +const styles = StyleSheet.create({ + header: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingHorizontal: 16, + paddingVertical: 12, + backgroundColor: theme.colors.surface, + borderBottomWidth: 1, + borderBottomColor: theme.colors.border, + width: "100%", + height: 60, + }, + userInfo: { + flexDirection: 'row', + alignItems: 'center', + height: 46, + }, + image: { + width: theme.components.header.imageSize, + height: theme.components.header.imageSize, + borderRadius: theme.components.header.imageSize / 2, + marginRight: 10, + }, + username: { + fontSize: 16, + fontWeight: '500', + color: theme.colors.textPrimary, + }, + logoutButton: { + backgroundColor: theme.colors.transparent, + justifyContent: 'center', + marginLeft: 8, + }, + + adminButton: { + backgroundColor: theme.colors.primary, + paddingHorizontal: 12, + paddingVertical: 6, + borderRadius: 8, + justifyContent: 'center', + alignItems: 'center', + marginHorizontal: 8, + }, + + adminButtonText: { + color: theme.colors.surface, + fontSize: 14, + fontWeight: '600', + }, +}); + +export default styles; \ No newline at end of file diff --git a/frontend/src/components/header/Header.tsx b/frontend/src/components/header/Header.tsx new file mode 100644 index 0000000..26de3e1 --- /dev/null +++ b/frontend/src/components/header/Header.tsx @@ -0,0 +1,31 @@ +import React from "react"; +import {useNavigation} from "@react-navigation/native"; +import {NativeStackNavigationProp} from "@react-navigation/native-stack"; +import {View, Text, Pressable} from "react-native"; +import {MaterialIcons} from "@expo/vector-icons"; +import type {RootStackParamList} from "../../navigation/Navigation"; +import styles from "./Header.style"; + +const Header = () => { + const navigation = useNavigation>(); + + return ( + + + AutoNow + + + + navigation.navigate("test")} style={styles.adminButton}> + Admin + + + + + + + + ); +}; + +export default Header; \ No newline at end of file From 1cc982b3e319103281cb20b8f264abaae71278ca Mon Sep 17 00:00:00 2001 From: Stoynov Date: Thu, 30 Apr 2026 12:49:06 +0300 Subject: [PATCH 07/13] Add home --- frontend/src/screens/home/Home.style.tsx | 9 +++++++++ frontend/src/screens/home/Home.tsx | 14 ++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 frontend/src/screens/home/Home.style.tsx create mode 100644 frontend/src/screens/home/Home.tsx diff --git a/frontend/src/screens/home/Home.style.tsx b/frontend/src/screens/home/Home.style.tsx new file mode 100644 index 0000000..496a10a --- /dev/null +++ b/frontend/src/screens/home/Home.style.tsx @@ -0,0 +1,9 @@ +import {StyleSheet} from 'react-native'; + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, +}); + +export default styles; \ No newline at end of file diff --git a/frontend/src/screens/home/Home.tsx b/frontend/src/screens/home/Home.tsx new file mode 100644 index 0000000..61a6bc0 --- /dev/null +++ b/frontend/src/screens/home/Home.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import {View} from 'react-native'; +import styles from './Home.style'; +import Header from "../../components/header/Header"; + +const Home = () => { + return ( + +
+ + ); +}; + +export default Home; \ No newline at end of file From dc5df5bf369104e859c8a52cb3bd1da6a1de2d31 Mon Sep 17 00:00:00 2001 From: Stoynov Date: Thu, 30 Apr 2026 12:49:30 +0300 Subject: [PATCH 08/13] Apply everything to app.tsx --- frontend/App.tsx | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/frontend/App.tsx b/frontend/App.tsx index 0329d0c..be7c14e 100644 --- a/frontend/App.tsx +++ b/frontend/App.tsx @@ -1,20 +1,14 @@ -import { StatusBar } from 'expo-status-bar'; -import { StyleSheet, Text, View } from 'react-native'; +import {NavigationContainer} from '@react-navigation/native'; +import Navigation from './src/navigation/Navigation'; +import {I18nextProvider} from 'react-i18next'; +import i18n from "../frontend/src/config/i18n"; export default function App() { - return ( - - Open up App.tsx to start working on your app! - - - ); + return ( + + + + + + ); } - -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: '#fff', - alignItems: 'center', - justifyContent: 'center', - }, -}); From 60fd076aeb7d91078fc85d7668bdafdd90f61669 Mon Sep 17 00:00:00 2001 From: Stoynov Date: Thu, 30 Apr 2026 15:22:13 +0300 Subject: [PATCH 09/13] Add orientation logic --- frontend/app.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/frontend/app.json b/frontend/app.json index b1c39b7..bea3b49 100644 --- a/frontend/app.json +++ b/frontend/app.json @@ -3,7 +3,7 @@ "name": "frontend-temp", "slug": "frontend-temp", "version": "1.0.0", - "orientation": "portrait", + "orientation": "default", "icon": "./assets/icon.png", "userInterfaceStyle": "light", "newArchEnabled": true, @@ -13,7 +13,9 @@ "backgroundColor": "#ffffff" }, "ios": { - "supportsTablet": true + "supportsTablet": true, + "requireFullScreen": false, + "orientation": "default" }, "android": { "adaptiveIcon": { @@ -21,7 +23,8 @@ "backgroundColor": "#ffffff" }, "edgeToEdgeEnabled": true, - "predictiveBackGestureEnabled": false + "predictiveBackGestureEnabled": false, + "orientation": "default" }, "web": { "favicon": "./assets/favicon.png" From 8e6d21d473cc669dab8c1500be358ae73eb14284 Mon Sep 17 00:00:00 2001 From: Stoynov Date: Thu, 30 Apr 2026 15:45:21 +0300 Subject: [PATCH 10/13] Delete --- frontend/.claude/settings.local.json | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 frontend/.claude/settings.local.json diff --git a/frontend/.claude/settings.local.json b/frontend/.claude/settings.local.json deleted file mode 100644 index f3766bd..0000000 --- a/frontend/.claude/settings.local.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "permissions": { - "allow": [ - "Bash(npx create-expo-app@latest *)", - "Bash(mv frontend-temp/* frontend/)", - "Bash(mv frontend-temp/.gitignore frontend/)", - "Bash(rm -rf frontend-temp)", - "Bash(npm --version)", - "Bash(npm install *)" - ] - } -} From 62b7a303f5280a597f44a59486a8810e35b619e4 Mon Sep 17 00:00:00 2001 From: Stoynov Date: Thu, 30 Apr 2026 15:52:31 +0300 Subject: [PATCH 11/13] Improve on navigation --- frontend/src/components/header/Header.style.tsx | 6 ++++-- frontend/src/screens/home/Home.style.tsx | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/header/Header.style.tsx b/frontend/src/components/header/Header.style.tsx index efc149e..484a562 100644 --- a/frontend/src/components/header/Header.style.tsx +++ b/frontend/src/components/header/Header.style.tsx @@ -6,13 +6,15 @@ const styles = StyleSheet.create({ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', - paddingHorizontal: 16, + paddingHorizontal: 20, paddingVertical: 12, + marginVertical: 36, backgroundColor: theme.colors.surface, borderBottomWidth: 1, borderBottomColor: theme.colors.border, - width: "100%", + width: "80%", height: 60, + borderRadius: 20 }, userInfo: { flexDirection: 'row', diff --git a/frontend/src/screens/home/Home.style.tsx b/frontend/src/screens/home/Home.style.tsx index 496a10a..217fa42 100644 --- a/frontend/src/screens/home/Home.style.tsx +++ b/frontend/src/screens/home/Home.style.tsx @@ -2,7 +2,8 @@ import {StyleSheet} from 'react-native'; const styles = StyleSheet.create({ container: { - flex: 1, + justifyContent: "center", + alignItems: "center", }, }); From d022ec8917aa07775ab7ca0bba923190bc218f12 Mon Sep 17 00:00:00 2001 From: Stoynov Date: Thu, 30 Apr 2026 15:54:50 +0300 Subject: [PATCH 12/13] Improve navigation --- frontend/src/components/header/Header.style.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/header/Header.style.tsx b/frontend/src/components/header/Header.style.tsx index 484a562..9f064dc 100644 --- a/frontend/src/components/header/Header.style.tsx +++ b/frontend/src/components/header/Header.style.tsx @@ -14,7 +14,7 @@ const styles = StyleSheet.create({ borderBottomColor: theme.colors.border, width: "80%", height: 60, - borderRadius: 20 + borderRadius: 20, }, userInfo: { flexDirection: 'row', @@ -29,7 +29,8 @@ const styles = StyleSheet.create({ }, username: { fontSize: 16, - fontWeight: '500', + fontFamily: 'Courier New', + fontWeight: '800', color: theme.colors.textPrimary, }, logoutButton: { From 5e538e2e0740fd75979c0a9fa62ccbfaf0c827e0 Mon Sep 17 00:00:00 2001 From: Stoynov Date: Thu, 30 Apr 2026 16:17:28 +0300 Subject: [PATCH 13/13] Add theme logic --- frontend/App.tsx | 13 ++++--- .../src/assets/images/logout-svgrepo-com.svg | 7 ---- .../src/components/header/Header.style.tsx | 7 +--- frontend/src/components/header/Header.tsx | 15 +++++++- frontend/src/constants/theme.tsx | 30 ++++++++++++++- frontend/src/hooks/useTheme.tsx | 37 +++++++++++++++++++ 6 files changed, 88 insertions(+), 21 deletions(-) delete mode 100644 frontend/src/assets/images/logout-svgrepo-com.svg create mode 100644 frontend/src/hooks/useTheme.tsx diff --git a/frontend/App.tsx b/frontend/App.tsx index be7c14e..d9bc4f6 100644 --- a/frontend/App.tsx +++ b/frontend/App.tsx @@ -2,13 +2,16 @@ import {NavigationContainer} from '@react-navigation/native'; import Navigation from './src/navigation/Navigation'; import {I18nextProvider} from 'react-i18next'; import i18n from "../frontend/src/config/i18n"; +import {ThemeProvider} from './src/hooks/useTheme'; export default function App() { return ( - - - - - + + + + + + + ); } diff --git a/frontend/src/assets/images/logout-svgrepo-com.svg b/frontend/src/assets/images/logout-svgrepo-com.svg deleted file mode 100644 index bb35cf0..0000000 --- a/frontend/src/assets/images/logout-svgrepo-com.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/frontend/src/components/header/Header.style.tsx b/frontend/src/components/header/Header.style.tsx index 9f064dc..35500be 100644 --- a/frontend/src/components/header/Header.style.tsx +++ b/frontend/src/components/header/Header.style.tsx @@ -1,7 +1,6 @@ import { StyleSheet } from 'react-native'; -import { theme } from '../../constants/theme'; -const styles = StyleSheet.create({ +export const createStyles = (theme: any) => StyleSheet.create({ header: { flexDirection: 'row', justifyContent: 'space-between', @@ -54,6 +53,4 @@ const styles = StyleSheet.create({ fontSize: 14, fontWeight: '600', }, -}); - -export default styles; \ No newline at end of file +}); \ No newline at end of file diff --git a/frontend/src/components/header/Header.tsx b/frontend/src/components/header/Header.tsx index 26de3e1..6f6b26c 100644 --- a/frontend/src/components/header/Header.tsx +++ b/frontend/src/components/header/Header.tsx @@ -4,10 +4,13 @@ import {NativeStackNavigationProp} from "@react-navigation/native-stack"; import {View, Text, Pressable} from "react-native"; import {MaterialIcons} from "@expo/vector-icons"; import type {RootStackParamList} from "../../navigation/Navigation"; -import styles from "./Header.style"; +import { createStyles } from "./Header.style"; +import { useTheme } from "../../hooks/useTheme"; const Header = () => { const navigation = useNavigation>(); + const { theme, toggleTheme, themeMode } = useTheme(); + const styles = createStyles(theme); return ( @@ -16,12 +19,20 @@ const Header = () => { + + + + navigation.navigate("test")} style={styles.adminButton}> Admin - + diff --git a/frontend/src/constants/theme.tsx b/frontend/src/constants/theme.tsx index f23540b..96e25e2 100644 --- a/frontend/src/constants/theme.tsx +++ b/frontend/src/constants/theme.tsx @@ -1,4 +1,4 @@ -export const theme = { +export const lightTheme = { colors: { primary: '#444444', secondary: '#CECECC', @@ -114,4 +114,30 @@ export const theme = { } }; -export default theme; \ No newline at end of file +export const darkTheme = { + colors: { + primary: '#BB86FC', + secondary: '#03DAC6', + background: '#121212', + surface: '#1E1E1E', + textPrimary: '#E1E1E1', + textSecondary: '#A1A1A1', + border: '#2C2C2C', + ripple: 'rgba(255,255,255,0.1)', + shadow: '#000', + transparent: 'transparent', + textTertiary: '#B1B1B1', + textValidationError: '#CF6679', + error: '#CF6679' + }, + spacing: lightTheme.spacing, + fontSizes: lightTheme.fontSizes, + radii: lightTheme.radii, + sizes: lightTheme.sizes, + iconSizes: lightTheme.iconSizes, + elevation: lightTheme.elevation, + lineHeights: lightTheme.lineHeights, + components: lightTheme.components, +}; + +export const theme = lightTheme; \ No newline at end of file diff --git a/frontend/src/hooks/useTheme.tsx b/frontend/src/hooks/useTheme.tsx new file mode 100644 index 0000000..cd153c3 --- /dev/null +++ b/frontend/src/hooks/useTheme.tsx @@ -0,0 +1,37 @@ +import React, { createContext, useContext, useState, ReactNode } from 'react'; +import { lightTheme, darkTheme } from '../constants/theme'; + +type Theme = typeof lightTheme; +type ThemeMode = 'light' | 'dark'; + +interface ThemeContextType { + theme: Theme; + themeMode: ThemeMode; + toggleTheme: () => void; +} + +const ThemeContext = createContext(undefined); + +export const ThemeProvider = ({ children }: { children: ReactNode }) => { + const [themeMode, setThemeMode] = useState('light'); + + const toggleTheme = () => { + setThemeMode((prev) => (prev === 'light' ? 'dark' : 'light')); + }; + + const theme = themeMode === 'light' ? lightTheme : darkTheme; + + return ( + + {children} + + ); +}; + +export const useTheme = () => { + const context = useContext(ThemeContext); + if (!context) { + throw new Error('useTheme must be used within ThemeProvider'); + } + return context; +};