17 Commits

Author SHA1 Message Date
Tomas Dvorak 67dc5cc737 feat(ui): enhance frontend architecture and improve user experience
CI/CD Pipeline / Test (push) Successful in 21m56s
CI/CD Pipeline / Security Scan (push) Successful in 10m54s
CI/CD Pipeline / Build and Push Images (push) Failing after 2m12s
Refactor the frontend to use a more consistent design system and improve the overall user interface and experience.

- Implement a consistent use of `Card` components across various pages (Dashboard, Settings, Notes, etc.).
- Improve layout responsiveness and spacing in several modules.
- Enhance the Tasks page with drag-and-drop status updates and a Kanban-style view.
- Update the Calendar view with better color coding for task priorities and types.
- Refactor the Bookmarks page to use a grid layout with improved card previews.
- Update the Nginx configuration to handle SPA routing and health checks more effectively.
- Standardize import paths using `@/` aliases.
- Fix minor bugs in message sending and loading states.
- Update Docker configuration to build from source and use a specific backend port.
2026-05-20 16:36:48 +02:00
Tomas Dvorak 1e377a01b0 chore(config): remove dragonflydb and update deployment documentation
CI/CD Pipeline / Test (push) Failing after 14m0s
CI/CD Pipeline / Security Scan (push) Successful in 10m59s
CI/CD Pipeline / Build and Push Images (push) Has been skipped
Remove all references to DragonflyDB from the codebase, environment templates, and documentation following its removal from the service architecture. This includes cleaning up Docker configurations, CI/CD workflows, and production guides.

- **Cleanup**: Deleted `dragonfly.conf` and removed DragonflyDB service from `docker-compose.yml`.
- **Environment**: Removed `DRAGONFLY_PASSWORD` and `DRAGONFLY_ADDR` from `.env.example` and `docker-entrypoint.sh`.
- **Documentation**: Updated `README.md`, `PRODUCTION_DEPLOYMENT.md`, and `QUICK_START_PRODUCTION.md` to reflect a 2-service architecture (Trackeep + Postgres).
- **CI/CD**: Updated GitHub Actions to use Go 1.25.
- **Testing**: Updated `test-production.sh` to remove DragonflyDB variable validation.
2026-05-10 11:25:33 +02:00
Tomas Dvorak 6c448b336a refactor: unify docker deployment and restructure frontend architecture
This commit implements a unified Docker deployment strategy, moving from separate frontend and backend images to a single, multi-stage build image containing both services. It also introduces a major reorganization of the frontend directory structure and simplifies the environment configuration.

Key changes:
- **Deployment**: Added a multi-stage `Dockerfile` and `docker-entrypoint.sh` to package the Go backend and Nginx-served frontend into a single container.
- **CI/CD**: Updated GitHub Actions workflows (`ci-cd.yml`, `release.yml`) to build and push the new unified image instead of separate ones.
- **Frontend Refactor**: Reorganized `frontend/src/pages` into a domain-driven directory structure (e.g., `auth/`, `admin/`, `content/`, `communication/`, `productivity/`, `settings/`, `misc/`).
- **Configuration**: Simplified `.env.example` and updated `docker-compose.yml` to reflect the unified service model and single host port.
- **Cleanup**: Removed deprecated `docker-compose.demo.yml`, `docker-compose.prod.yml`, and various unused frontend components and services.
- **Backend**: Refactored configuration loading to use exported `GetDurationEnv` for better consistency.
2026-05-10 10:48:41 +02:00
Tomas Dvorak c6a99c7e21 small fix, don't worry about it 2026-04-10 12:06:01 +02:00
Tomas Dvorak 954a1a1080 feat: migrate to DragonflyDB and clean up environment configuration
- Replace Redis with DragonflyDB for better performance and memory efficiency
- Remove redundant environment variables (POSTGRES_*, ENCRYPTION_KEY, OAUTH_SERVICE_URL)
- Consolidate database configuration to use single DB_* variables
- Use JWT_SECRET for both JWT tokens and encryption
- Remove PORT variable redundancy, use BACKEND_PORT consistently
- Clean up docker-compose configurations for dev/prod consistency
- Add DragonflyDB configuration with optimized memory usage
- Remove redis.conf as it's no longer needed
- Update health checks to use Redis-compatible CLI for DragonflyDB
- Add missing VITE_API_URL to production frontend
- Fix GitHub Actions to use correct go.sum path
- Clean up development directories and unused files
2026-03-05 23:51:34 +01:00
Tomas Dvorak f3a835caa2 feat: fully integrate DragonflyDB with application
- Add Redis client initialization with DragonflyDB connection
- Update session middleware to use DragonflyDB with fallback to memory
- Update cache middleware to use DragonflyDB for persistent caching
- Add proper error handling and connection timeouts
- Implement session storage in DragonflyDB with 24-hour expiration
- Add cache invalidation middleware for DragonflyDB
- Maintain backward compatibility with in-memory fallbacks
2026-03-03 12:46:18 +01:00
Tomas Dvorak dee7011192 fix: add missing VITE_API_URL to production frontend
- Add VITE_API_URL environment variable to production frontend
- Ensures frontend can connect to backend API in production
2026-03-03 12:39:08 +01:00
Tomas Dvorak ebd4ba649d fix: update GitHub Actions to use correct go.sum path
- Add cache-dependency-path: backend/go.sum for Go setup action
- Fixes cache restore failures in CI/CD pipeline
2026-03-03 12:32:28 +01:00
Tomas Dvorak 9a580c77d2 feat: migrate to DragonflyDB and clean up environment configuration
- Replace Redis with DragonflyDB for better performance and memory efficiency
- Remove redundant environment variables (POSTGRES_*, ENCRYPTION_KEY, OAUTH_SERVICE_URL)
- Consolidate database configuration to use single DB_* variables
- Use JWT_SECRET for both JWT tokens and encryption
- Remove PORT variable redundancy, use BACKEND_PORT consistently
- Clean up docker-compose configurations for dev/prod consistency
- Add DragonflyDB configuration with optimized memory usage
- Remove redis.conf as it's no longer needed
- Update health checks to use Redis-compatible CLI for DragonflyDB
2026-03-03 12:20:08 +01:00
Tomas Dvorak fc913b5641 fix build 2026-03-03 11:11:55 +01:00
Tomas Dvorak 874efd5452 chore: update gitignore to ensure playwright-cli and desloppify are ignored 2026-03-03 11:07:11 +01:00
Tomáš Dvořák 1e8bf270a1 Delete .desloppify directory 2026-03-03 11:05:11 +01:00
Tomáš Dvořák d82e52ad98 Delete .playwright-cli directory 2026-03-03 11:04:19 +01:00
Tomas Dvorak 083373a24f feat: major feature updates and cleanup
- Add Redis architecture implementation
- Update browser extension functionality
- Clean up deprecated files and documentation
- Enhance backend handlers for auth, messages, search
- Add new configuration options and settings
- Update Docker and deployment configurations
2026-03-03 11:03:37 +01:00
Tomas Dvorak 446bc7acfb fix: remove verbatimModuleSyntax to resolve CI TypeScript build errors
- Remove verbatimModuleSyntax: true from tsconfig.app.json
- This option caused async/await syntax errors in CI/CD environment
- Build now works consistently across local and CI environments
- Fixes TS1308 errors on await expressions in updateService.ts
2026-02-27 19:24:18 +01:00
Tomas Dvorak 90f0b90cc7 fix: remove verbatimModuleSyntax to resolve CI TypeScript build errors
- Remove verbatimModuleSyntax: true from tsconfig.app.json
- This option caused async/await syntax errors in CI/CD environment
- Build now works consistently across local and CI environments
- Fixes TS1308 errors on await expressions in updateService.ts
2026-02-27 19:24:05 +01:00
Tomas Dvorak ecd31f4e3b small fix 2026-02-27 19:11:40 +01:00
504 changed files with 196401 additions and 83765 deletions
-31
View File
@@ -1,31 +0,0 @@
{
"languages": {},
"review_max_age_days": 30,
"holistic_max_age_days": 30,
"generate_scorecard": true,
"badge_path": "scorecard.png",
"exclude": [],
"ignore": [
"test_coverage::frontend/src/pages/Login.tsx",
"test_coverage::frontend/src/App.tsx"
],
"ignore_metadata": {
"test_coverage::frontend/src/pages/Login.tsx": {
"note": "Login page - test coverage is separate effort, permanently ignore",
"added_at": "2026-02-18T13:23:38+00:00"
},
"test_coverage::frontend/src/App.tsx": {
"note": "Main App component - test coverage is separate effort, permanently ignore",
"added_at": "2026-02-18T13:26:59+00:00"
}
},
"zone_overrides": {},
"review_dimensions": [],
"review_allow_custom_dimensions": false,
"review_custom_dimensions": [],
"large_files_threshold": 0,
"props_threshold": 0,
"finding_noise_budget": 10,
"finding_noise_global_budget": 0,
"target_strict_score": 95
}
-742
View File
@@ -1,742 +0,0 @@
{
"command": "status",
"overall_score": 75.0,
"objective_score": 100.0,
"strict_score": 59.3,
"strict_all_detected": 59.1,
"dimension_scores": {
"File health": {
"score": 100.0,
"strict": 87.6,
"checks": 143,
"issues": 0,
"tier": 3,
"detectors": {
"structural": {
"potential": 143,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
}
}
},
"Code quality": {
"score": 100.0,
"strict": 67.2,
"checks": 1211,
"issues": 0,
"tier": 3,
"detectors": {
"unused": {
"potential": 143,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
},
"logs": {
"potential": 143,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
},
"exports": {
"potential": 305,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
},
"deprecated": {
"potential": 2,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
},
"props": {
"potential": 76,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
},
"smells": {
"potential": 143,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
},
"react": {
"potential": 14,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
},
"orphaned": {
"potential": 146,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
},
"flat_dirs": {
"potential": 25,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
},
"naming": {
"potential": 23,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
},
"facade": {
"potential": 146,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
},
"patterns": {
"potential": 3,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
},
"single_use": {
"potential": 42,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
}
}
},
"Duplication": {
"score": 100.0,
"strict": 99.4,
"checks": 288,
"issues": 0,
"tier": 3,
"detectors": {
"dupes": {
"potential": 288,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
}
}
},
"Test health": {
"score": 100.0,
"strict": 48.6,
"checks": 2246,
"issues": 0,
"tier": 4,
"detectors": {
"test_coverage": {
"potential": 2109,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
},
"subjective_review": {
"potential": 137,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
}
}
},
"Security": {
"score": 100.0,
"strict": 98.6,
"checks": 289,
"issues": 0,
"tier": 4,
"detectors": {
"security": {
"potential": 143,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
},
"cycles": {
"potential": 146,
"pass_rate": 1.0,
"issues": 0,
"weighted_failures": 0.0
}
}
},
"Naming Quality": {
"score": 0.0,
"strict": 0.0,
"checks": 10,
"issues": 0,
"tier": 4,
"detectors": {
"subjective_assessment": {
"potential": 10,
"pass_rate": 0.0,
"issues": 0,
"weighted_failures": 10.0
}
}
},
"Error Consistency": {
"score": 0.0,
"strict": 0.0,
"checks": 10,
"issues": 0,
"tier": 4,
"detectors": {
"subjective_assessment": {
"potential": 10,
"pass_rate": 0.0,
"issues": 0,
"weighted_failures": 10.0
}
}
},
"Abstraction Fit": {
"score": 0.0,
"strict": 0.0,
"checks": 10,
"issues": 0,
"tier": 4,
"detectors": {
"subjective_assessment": {
"potential": 10,
"pass_rate": 0.0,
"issues": 0,
"weighted_failures": 10.0
}
}
},
"Logic Clarity": {
"score": 0.0,
"strict": 0.0,
"checks": 10,
"issues": 0,
"tier": 4,
"detectors": {
"subjective_assessment": {
"potential": 10,
"pass_rate": 0.0,
"issues": 0,
"weighted_failures": 10.0
}
}
},
"AI Generated Debt": {
"score": 0.0,
"strict": 0.0,
"checks": 10,
"issues": 0,
"tier": 4,
"detectors": {
"subjective_assessment": {
"potential": 10,
"pass_rate": 0.0,
"issues": 0,
"weighted_failures": 10.0
}
}
},
"Type Safety": {
"score": 0.0,
"strict": 0.0,
"checks": 10,
"issues": 0,
"tier": 4,
"detectors": {
"subjective_assessment": {
"potential": 10,
"pass_rate": 0.0,
"issues": 0,
"weighted_failures": 10.0
}
}
},
"Contract Coherence": {
"score": 0.0,
"strict": 0.0,
"checks": 10,
"issues": 0,
"tier": 4,
"detectors": {
"subjective_assessment": {
"potential": 10,
"pass_rate": 0.0,
"issues": 0,
"weighted_failures": 10.0
}
}
}
},
"stats": {
"total": 873,
"open": 0,
"fixed": 20,
"auto_resolved": 1,
"wontfix": 768,
"false_positive": 84,
"by_tier": {
"1": {
"open": 0,
"fixed": 17,
"auto_resolved": 0,
"wontfix": 8,
"false_positive": 0
},
"2": {
"open": 0,
"fixed": 3,
"auto_resolved": 1,
"wontfix": 376,
"false_positive": 26
},
"3": {
"open": 0,
"fixed": 0,
"auto_resolved": 0,
"wontfix": 245,
"false_positive": 58
},
"4": {
"open": 0,
"fixed": 0,
"auto_resolved": 0,
"wontfix": 139,
"false_positive": 0
}
}
},
"scan_count": 10,
"last_scan": "2026-02-18T13:28:26+00:00",
"by_tier": {
"1": {
"open": 0,
"fixed": 17,
"auto_resolved": 0,
"wontfix": 8,
"false_positive": 0
},
"2": {
"open": 0,
"fixed": 3,
"auto_resolved": 1,
"wontfix": 376,
"false_positive": 26
},
"3": {
"open": 0,
"fixed": 0,
"auto_resolved": 0,
"wontfix": 245,
"false_positive": 58
},
"4": {
"open": 0,
"fixed": 0,
"auto_resolved": 0,
"wontfix": 139,
"false_positive": 0
}
},
"ignores": [
"test_coverage::frontend/src/pages/Login.tsx",
"test_coverage::frontend/src/App.tsx"
],
"suppression": {
"last_ignored": 1,
"last_raw_findings": 853,
"last_suppressed_pct": 0.1,
"last_ignore_patterns": 2,
"recent_scans": 5,
"recent_ignored": 1,
"recent_raw_findings": 4265,
"recent_suppressed_pct": 0.0
},
"detector_transparency": {
"rows": [
{
"detector": "exports",
"visible": 305,
"suppressed": 0,
"excluded": 0,
"total_detected": 305
},
{
"detector": "smells",
"visible": 215,
"suppressed": 0,
"excluded": 1,
"total_detected": 216
},
{
"detector": "subjective_review",
"visible": 138,
"suppressed": 0,
"excluded": 0,
"total_detected": 138
},
{
"detector": "test_coverage",
"visible": 49,
"suppressed": 1,
"excluded": 0,
"total_detected": 50
},
{
"detector": "structural",
"visible": 25,
"suppressed": 0,
"excluded": 0,
"total_detected": 25
},
{
"detector": "security",
"visible": 18,
"suppressed": 0,
"excluded": 0,
"total_detected": 18
},
{
"detector": "logs",
"visible": 6,
"suppressed": 0,
"excluded": 0,
"total_detected": 6
},
{
"detector": "dupes",
"visible": 3,
"suppressed": 0,
"excluded": 0,
"total_detected": 3
},
{
"detector": "deprecated",
"visible": 0,
"suppressed": 0,
"excluded": 2,
"total_detected": 2
},
{
"detector": "flat_dirs",
"visible": 2,
"suppressed": 0,
"excluded": 0,
"total_detected": 2
},
{
"detector": "unused",
"visible": 2,
"suppressed": 0,
"excluded": 0,
"total_detected": 2
},
{
"detector": "cycles",
"visible": 1,
"suppressed": 0,
"excluded": 0,
"total_detected": 1
},
{
"detector": "react",
"visible": 1,
"suppressed": 0,
"excluded": 0,
"total_detected": 1
}
],
"totals": {
"visible": 765,
"suppressed": 1,
"excluded": 3,
"detectors": 13
}
},
"potentials": {
"typescript": {
"logs": 143,
"unused": 143,
"exports": 305,
"deprecated": 2,
"structural": 143,
"flat_dirs": 25,
"props": 76,
"single_use": 42,
"coupling": 0,
"cycles": 146,
"orphaned": 146,
"patterns": 3,
"naming": 23,
"facade": 146,
"test_coverage": 2109,
"smells": 143,
"react": 14,
"security": 143,
"subjective_review": 137,
"dupes": 288
}
},
"codebase_metrics": {
"typescript": {
"total_files": 151,
"total_loc": 40054,
"total_directories": 25
}
},
"strict_target": {
"target": 95.0,
"current": 59.3,
"gap": 35.7,
"state": "below",
"warning": null
},
"narrative": {
"phase": "stagnation",
"headline": "All T1 and T2 items cleared!",
"dimensions": {
"lowest_dimensions": [
{
"name": "Naming Quality",
"strict": 0.0,
"issues": 0,
"impact": 0.0,
"subjective": true,
"impact_description": "re-review to improve"
},
{
"name": "Error Consistency",
"strict": 0.0,
"issues": 0,
"impact": 0.0,
"subjective": true,
"impact_description": "re-review to improve"
},
{
"name": "Abstraction Fit",
"strict": 0.0,
"issues": 0,
"impact": 0.0,
"subjective": true,
"impact_description": "re-review to improve"
}
],
"biggest_gap_dimensions": [
{
"name": "Test health",
"lenient": 100.0,
"strict": 48.6,
"gap": 51.4,
"wontfix_count": 187
},
{
"name": "Code quality",
"lenient": 100.0,
"strict": 67.2,
"gap": 32.8,
"wontfix_count": 534
},
{
"name": "File health",
"lenient": 100.0,
"strict": 87.6,
"gap": 12.4,
"wontfix_count": 25
}
],
"stagnant_dimensions": [
{
"name": "File health",
"strict": 87.6,
"stuck_scans": 5
},
{
"name": "Code quality",
"strict": 67.2,
"stuck_scans": 5
},
{
"name": "Duplication",
"strict": 99.4,
"stuck_scans": 5
},
{
"name": "Security",
"strict": 98.6,
"stuck_scans": 5
},
{
"name": "Naming Quality",
"strict": 0.0,
"stuck_scans": 5
},
{
"name": "Error Consistency",
"strict": 0.0,
"stuck_scans": 5
},
{
"name": "Abstraction Fit",
"strict": 0.0,
"stuck_scans": 5
},
{
"name": "Logic Clarity",
"strict": 0.0,
"stuck_scans": 5
},
{
"name": "AI Generated Debt",
"strict": 0.0,
"stuck_scans": 5
},
{
"name": "Type Safety",
"strict": 0.0,
"stuck_scans": 5
},
{
"name": "Contract Coherence",
"strict": 0.0,
"stuck_scans": 5
}
]
},
"actions": [
{
"priority": 1,
"type": "debt_review",
"detector": null,
"description": "7.8 pts of wontfix debt \u2014 review stale decisions",
"command": "desloppify show --status wontfix",
"gap": 7.8,
"lane": "debt_review"
}
],
"strategy": {
"fixer_leverage": {
"auto_fixable_count": 0,
"total_count": 0,
"coverage": 0.0,
"impact_ratio": 0.0,
"recommendation": "none"
},
"lanes": {
"debt_review": {
"actions": [
1
],
"file_count": 0,
"total_impact": 0.0,
"automation": "manual",
"run_first": false
}
},
"can_parallelize": false,
"hint": "Try a different dimension to break the plateau."
},
"tools": {
"fixers": [],
"move": {
"available": true,
"relevant": false,
"reason": null,
"usage": "desloppify move <source> <dest> [--dry-run]"
},
"plan": {
"command": "desloppify plan",
"description": "Generate prioritized markdown cleanup plan"
},
"badge": {
"generated": true,
"in_readme": true,
"path": "scorecard.png",
"recommendation": null
}
},
"debt": {
"overall_gap": 7.8,
"wontfix_count": 768,
"worst_dimension": "Test health",
"worst_gap": 51.4,
"trend": "stable"
},
"milestone": "All T1 and T2 items cleared!",
"primary_action": {
"priority": 1,
"type": "debt_review",
"detector": null,
"command": "desloppify show --status wontfix",
"description": "7.8 pts of wontfix debt \u2014 review stale decisions",
"impact": null,
"lane": "debt_review",
"count": null
},
"why_now": "Progress is plateaued, so the top action is the best chance to break the plateau.",
"verification_step": {
"command": "desloppify show --status wontfix",
"reason": "Re-check stale wontfix decisions before treating strict score as stable.",
"success_signal": "Wontfix list reflects only intentional and still-valid exceptions."
},
"risk_flags": [
{
"type": "wontfix_gap",
"severity": "medium",
"message": "7.8 strict-score points are masked by wontfix debt (768 items).",
"command": "desloppify show --status wontfix"
}
],
"strict_target": {
"target": 95.0,
"current": 59.3,
"gap": 35.7,
"state": "below",
"warning": null
},
"reminders": [],
"reminder_history": {
"report_scores": 10,
"auto_fixers_available": 3,
"dry_run_first": 3,
"zone_classification": 3,
"feedback_nudge": 3,
"stagnant_nudge": 10,
"fp_calibration_security_production": 3,
"wontfix_growing": 3,
"fp_calibration_orphaned_production": 3
}
},
"config": {
"review_max_age_days": 30,
"holistic_max_age_days": 30,
"generate_scorecard": true,
"badge_path": "scorecard.png",
"exclude": [],
"ignore": [
"test_coverage::frontend/src/pages/Login.tsx",
"test_coverage::frontend/src/App.tsx"
],
"ignore_metadata": {
"test_coverage::frontend/src/pages/Login.tsx": {
"note": "Login page - test coverage is separate effort, permanently ignore",
"added_at": "2026-02-18T13:23:38+00:00"
},
"test_coverage::frontend/src/App.tsx": {
"note": "Main App component - test coverage is separate effort, permanently ignore",
"added_at": "2026-02-18T13:26:59+00:00"
}
},
"zone_overrides": {},
"review_dimensions": [],
"review_allow_custom_dimensions": false,
"review_custom_dimensions": [],
"large_files_threshold": 0,
"props_threshold": 0,
"finding_noise_budget": 10,
"finding_noise_global_budget": 0,
"target_strict_score": 95,
"languages": {}
}
}
File diff suppressed because it is too large Load Diff
-1
View File
@@ -2,7 +2,6 @@ node_modules
.git .git
.gitignore .gitignore
README.md README.md
.env
.env.local .env.local
.env.production .env.production
Dockerfile Dockerfile
+8 -107
View File
@@ -1,112 +1,13 @@
# Server Configuration # Trackeep Configuration for Casa OS
PORT=8080 # Only required variables - everything else is auto-configured
GIN_MODE=debug
READ_TIMEOUT=15s # Host port for the application (default: 8080)
WRITE_TIMEOUT=15s HOST_PORT=8080
IDLE_TIMEOUT=60s
SHUTDOWN_TIMEOUT=30s
# Database Configuration # Database Configuration
DB_TYPE=postgres DB_PASSWORD=your_secure_password_here
DB_HOST=localhost
DB_PORT=5432
DB_USER=trackeep DB_USER=trackeep
DB_PASSWORD=your_password_here
DB_NAME=trackeep DB_NAME=trackeep
DB_SSL_MODE=disable
# Docker Compose Database (used by docker-compose.yml) # JWT Secret (generate with: openssl rand -hex 32)
POSTGRES_DB=trackeep JWT_SECRET=your_jwt_secret_here_64_hex_characters_long_exactly
POSTGRES_USER=trackeep
POSTGRES_PASSWORD=your_secure_password_here
# JWT Configuration
# JWT_SECRET is auto-generated on startup and stored in jwt_secret.key
# You can override by setting JWT_SECRET environment variable if needed
JWT_EXPIRES_IN=24h
# Encryption Configuration
# ENCRYPTION_KEY is auto-generated on startup and stored in encryption.key
# You can override by setting ENCRYPTION_KEY environment variable if needed
# File Upload Configuration
UPLOAD_DIR=./uploads
MAX_FILE_SIZE=10485760
# CORS Configuration
CORS_ALLOWED_ORIGINS=*
# AI Services Configuration
LONGCAT_ON=false
LONGCAT_API_KEY=your_longcat_api_key_here
LONGCAT_BASE_URL=https://api.longcat.chat
LONGCAT_OPENAI_ENDPOINT=https://api.longcat.chat/openai
LONGCAT_ANTHROPIC_ENDPOINT=https://api.longcat.chat/anthropic
LONGCAT_MODEL=LongCat-Flash-Chat
LONGCAT_MODEL_THINKING=LongCat-Flash-Thinking
LONGCAT_FORMAT=openai
# Mistral AI Configuration
MISTRAL_ON=false
MISTRAL_API_KEY=your_mistral_api_key_here
MISTRAL_MODEL=mistral-small-latest
MISTRAL_MODEL_THINKING=mistral-large-latest
# Grok AI Configuration
GROK_ON=false
GROK_API_KEY=your_grok_api_key_here
GROK_BASE_URL=https://api.x.ai/v1
GROK_MODEL=grok-4-1-fast-non-reasoning-latest
GROK_MODEL_THINKING=grok-4-1-fast-reasoning-latest
# DeepSeek Configuration
DEEPSEEK_ON=false
DEEPSEEK_API_KEY=your_deepseek_api_key_here
DEEPSEEK_BASE_URL=https://api.deepseek.com
DEEPSEEK_MODEL=deepseek-chat
DEEPSEEK_MODEL_THINKING=deepseek-reasoner
# Ollama Configuration
OLLAMA_ON=false
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=llama3.1
OLLAMA_MODEL_THINKING=llama3.1
# OpenRouter Configuration
OPENROUTER_ON=false
OPENROUTER_API_KEY=your_openrouter_api_key_here
OPENROUTER_BASE_URL=https://openrouter.ai/api
OPENROUTER_MODEL=openrouter/auto
OPENROUTER_MODEL_THINKING=openrouter/auto
# Demo Mode Configuration
VITE_DEMO_MODE=false
# Browser Search API Configuration
BRAVE_API_KEY=your_brave_api_key_here
BRAVE_SEARCH_BASE_URL=https://api.search.brave.com/res/v1/web/search
SERPER_API_KEY=your_serper_api_key_here
SERPER_BASE_URL=https://google.serper.dev/search
SEARCH_API_PROVIDER=brave # Options: brave, serper, demo
# Search Configuration
SEARCH_RESULTS_LIMIT=10
SEARCH_CACHE_TTL=300
SEARCH_RATE_LIMIT=100
# Update Configuration
# Application version (used for update checking)
APP_VERSION=1.0.0
# OAuth service configuration (REQUIRED)
# The OAuth service must be running for updates to work
OAUTH_SERVICE_URL=http://localhost:9090
JWT_SECRET=your-jwt-secret-key
# Update settings
AUTO_UPDATE_CHECK=false
UPDATE_CHECK_INTERVAL=24h
PRERELEASE_UPDATES=false
# Note: No GitHub token configuration needed
# Updates use the OAuth service which handles GitHub authentication automatically
+11 -27
View File
@@ -36,7 +36,9 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v4 uses: actions/setup-go@v4
with: with:
go-version: '1.24' go-version: '1.25'
cache: true
cache-dependency-path: backend/go.sum
- name: Install backend dependencies - name: Install backend dependencies
run: | run: |
@@ -90,7 +92,9 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v4 uses: actions/setup-go@v4
with: with:
go-version: '1.24' go-version: '1.25'
cache: true
cache-dependency-path: backend/go.sum
- name: Run go vet - name: Run go vet
run: | run: |
@@ -124,43 +128,23 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata - name: Extract metadata
id: meta-backend id: meta
uses: docker/metadata-action@v4 uses: docker/metadata-action@v4
with: with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/backend images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: | tags: |
type=ref,event=branch type=ref,event=branch
type=ref,event=pr type=ref,event=pr
type=sha,prefix={{branch}}- type=sha,prefix={{branch}}-
type=raw,value=latest,enable={{is_default_branch}} type=raw,value=latest,enable={{is_default_branch}}
- name: Extract metadata - name: Build and push unified image
id: meta-frontend
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/frontend
tags: |
type=ref,event=branch
type=ref,event=pr
type=sha,prefix={{branch}}-
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push backend image
uses: docker/build-push-action@v4
with:
context: ./backend
push: true
tags: ${{ steps.meta-backend.outputs.tags }}
labels: ${{ steps.meta-backend.outputs.labels }}
- name: Build and push frontend image
uses: docker/build-push-action@v4 uses: docker/build-push-action@v4
with: with:
context: . context: .
file: ./frontend/Dockerfile
push: true push: true
tags: ${{ steps.meta-frontend.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta-frontend.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
# deploy: # deploy:
# name: Deploy to Production # name: Deploy to Production
+14 -41
View File
@@ -37,9 +37,6 @@ jobs:
build-and-push: build-and-push:
needs: extract-version needs: extract-version
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
matrix:
service: [backend, frontend]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -57,7 +54,7 @@ jobs:
id: meta id: meta
uses: docker/metadata-action@v5 uses: docker/metadata-action@v5
with: with:
images: ${{ env.REGISTRY }}/${{ matrix.service }} images: ${{ env.REGISTRY }}
tags: | tags: |
type=ref,event=tag type=ref,event=tag
type=semver,pattern={{version}} type=semver,pattern={{version}}
@@ -66,18 +63,12 @@ jobs:
version=${{ needs.extract-version.outputs.version }} version=${{ needs.extract-version.outputs.version }}
build-date=${{ github.event.head_commit.timestamp }} build-date=${{ github.event.head_commit.timestamp }}
commit=${{ github.sha }} commit=${{ github.sha }}
service=${{ matrix.service }}
prerelease=${{ needs.extract-version.outputs.is-prerelease }} prerelease=${{ needs.extract-version.outputs.is-prerelease }}
- name: Build and push ${{ matrix.service }} - name: Build and push unified image
uses: docker/build-push-action@v5 uses: docker/build-push-action@v5
with: with:
context: | context: .
backend=./backend
frontend=.
file: |
backend=./backend/Dockerfile
frontend=./frontend/Dockerfile
push: true push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
@@ -87,15 +78,15 @@ jobs:
- name: Generate SBOM - name: Generate SBOM
uses: anchore/sbom-action@v0 uses: anchore/sbom-action@v0
with: with:
image: ${{ env.REGISTRY }}/${{ matrix.service }}:${{ needs.extract-version.outputs.version }} image: ${{ env.REGISTRY }}:${{ needs.extract-version.outputs.version }}
format: spdx-json format: spdx-json
output-file: ./sbom-${{ matrix.service }}.spdx.json output-file: ./sbom.spdx.json
- name: Upload SBOM - name: Upload SBOM
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: sbom-${{ matrix.service }} name: sbom
path: ./sbom-${{ matrix.service }}.spdx.json path: ./sbom.spdx.json
create-github-release: create-github-release:
needs: [extract-version, build-and-push] needs: [extract-version, build-and-push]
@@ -107,26 +98,21 @@ jobs:
- name: Create Release - name: Create Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
with: with:
tag: v${{ needs.extract-version.outputs.version }}
name: Trackeep v${{ needs.extract-version.outputs.version }} name: Trackeep v${{ needs.extract-version.outputs.version }}
body: | body: |
## 🚀 Trackeep v${{ needs.extract-version.outputs.version }} ## 🚀 Trackeep v${{ needs.extract-version.outputs.version }}
### 🐳 Docker Images ### 🐳 Docker Image
- **Backend**: `ghcr.io/dvorinka/trackeep/backend:${{ needs.extract-version.outputs.version }}` - **Unified**: `ghcr.io/dvorinka/trackeep:${{ needs.extract-version.outputs.version }}`
- **Frontend**: `ghcr.io/dvorinka/trackeep/frontend:${{ needs.extract-version.outputs.version }}` - **Latest**: `ghcr.io/dvorinka/trackeep:latest`
- **Latest**: `ghcr.io/dvorinka/trackeep/backend:latest` and `ghcr.io/dvorinka/trackeep/frontend:latest`
### 📋 Changes ### 📋 Changes
${{ github.event.head_commit.message }} ${{ github.event.head_commit.message }}
### 🔧 Installation ### 🔧 Installation
```bash ```bash
# Set version # Deploy with docker compose
export APP_VERSION=${{ needs.extract-version.outputs.version }} docker compose up -d
# Deploy with production compose
docker compose -f docker-compose.prod.yml up -d
``` ```
### ⚡ Auto-Updates ### ⚡ Auto-Updates
@@ -138,12 +124,10 @@ jobs:
draft: false draft: false
prerelease: ${{ needs.extract-version.outputs.is-prerelease }} prerelease: ${{ needs.extract-version.outputs.is-prerelease }}
files: | files: sbom.spdx.json
sbom-backend.spdx.json
sbom-frontend.spdx.json
generate_release_notes: true generate_release_notes: true
update-docker-compose-prod: update-version-files:
needs: extract-version needs: extract-version
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@@ -168,17 +152,6 @@ jobs:
echo "✅ Backend updated to $VERSION" echo "✅ Backend updated to $VERSION"
fi fi
# Update docker-compose files
if [ -f "docker-compose.yml" ]; then
sed -i "s/APP_VERSION=.*/APP_VERSION=$VERSION/" docker-compose.yml
echo "✅ docker-compose.yml updated"
fi
if [ -f "docker-compose.prod.yml" ]; then
sed -i "s/APP_VERSION=.*/APP_VERSION=$VERSION/" docker-compose.prod.yml
echo "✅ docker-compose.prod.yml updated"
fi
echo "🎉 All version files updated to $VERSION" echo "🎉 All version files updated to $VERSION"
- name: Commit updated version files - name: Commit updated version files
+9 -2
View File
@@ -26,6 +26,9 @@ pids
*.pid *.pid
*.seed *.seed
*.pid.lock *.pid.lock
.playwright
.playwright-cli
.desloppify
# Coverage directory used by tools like istanbul # Coverage directory used by tools like istanbul
coverage/ coverage/
@@ -83,7 +86,7 @@ dist
# Gatsby files # Gatsby files
.cache/ .cache/
public /public
# Storybook build outputs # Storybook build outputs
.out .out
@@ -177,7 +180,7 @@ dist
# Gatsby files # Gatsby files
.cache/ .cache/
public /public
# Storybook build outputs # Storybook build outputs
.out .out
@@ -256,6 +259,10 @@ Thumbs.db
*.tmp *.tmp
*.temp *.temp
# Desktop app build artifacts
desktop/dist/
desktop/src-tauri/target/
# Lock files (keep package-lock.json but ignore yarn.lock if using npm) # Lock files (keep package-lock.json but ignore yarn.lock if using npm)
# yarn.lock # yarn.lock
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,18 +0,0 @@
- generic [ref=e26]:
- generic [ref=e27]:
- img "Trackeep Logo" [ref=e29]
- heading "Trackeep" [level=1] [ref=e30]
- paragraph [ref=e31]: Welcome back
- generic [ref=e32]:
- generic [ref=e35]: Registration Disabled
- paragraph [ref=e36]: Accounts can only be created by the administrator. Please contact your admin to get an account.
- generic [ref=e37]:
- generic [ref=e38]:
- generic [ref=e39]: Email
- textbox "Email" [ref=e40]:
- /placeholder: your@email.com
- generic [ref=e41]:
- generic [ref=e42]: Password
- textbox "Password" [ref=e43]:
- /placeholder: ••••••••
- button "Sign In" [ref=e44] [cursor=pointer]
@@ -1,21 +0,0 @@
- generic [ref=e26]:
- generic [ref=e27]:
- img "Trackeep Logo" [ref=e29]
- heading "Trackeep" [level=1] [ref=e30]
- paragraph [ref=e31]: Welcome back
- generic [ref=e32]:
- generic [ref=e35]: Registration Disabled
- paragraph [ref=e36]: Accounts can only be created by the administrator. Please contact your admin to get an account.
- generic [ref=e37]:
- generic [ref=e45]: Invalid credentials
- generic [ref=e38]:
- generic [ref=e39]: Email
- textbox "Email" [ref=e40]:
- /placeholder: your@email.com
- text: demo@trackeep.com
- generic [ref=e41]:
- generic [ref=e42]: Password
- textbox "Password" [ref=e43]:
- /placeholder: ••••••••
- text: password
- button "Sign In" [ref=e44] [cursor=pointer]
@@ -1 +0,0 @@
- paragraph [ref=e6]: Checking authentication...
@@ -1 +0,0 @@
- paragraph [ref=e6]: Checking authentication...
@@ -1 +0,0 @@
- paragraph [ref=e6]: Checking authentication...
@@ -1 +0,0 @@
- paragraph [ref=e6]: Checking authentication...
@@ -1 +0,0 @@
- paragraph [ref=e6]: Checking authentication...
@@ -1 +0,0 @@
- paragraph [ref=e6]: Checking authentication...
@@ -1 +0,0 @@
- paragraph [ref=e6]: Checking authentication...
@@ -1 +0,0 @@
- paragraph [ref=e6]: Checking authentication...
@@ -1 +0,0 @@
- paragraph [ref=e6]: Checking authentication...
@@ -1 +0,0 @@
- paragraph [ref=e6]: Checking authentication...
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,18 +0,0 @@
- generic [ref=e4]:
- generic [ref=e5]:
- img "Trackeep Logo" [ref=e7]
- heading "Trackeep" [level=1] [ref=e8]
- paragraph [ref=e9]: Welcome back
- generic [ref=e10]:
- generic [ref=e13]: Registration Disabled
- paragraph [ref=e14]: Accounts can only be created by the administrator. Please contact your admin to get an account.
- generic [ref=e15]:
- generic [ref=e16]:
- generic [ref=e17]: Email
- textbox "Email" [ref=e18]:
- /placeholder: your@email.com
- generic [ref=e19]:
- generic [ref=e20]: Password
- textbox "Password" [ref=e21]:
- /placeholder: ••••••••
- button "Sign In" [ref=e22] [cursor=pointer]
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,18 +0,0 @@
- generic [ref=e4]:
- generic [ref=e5]:
- img "Trackeep Logo" [ref=e7]
- heading "Trackeep" [level=1] [ref=e8]
- paragraph [ref=e9]: Welcome back
- generic [ref=e10]:
- generic [ref=e13]: Registration Disabled
- paragraph [ref=e14]: Accounts can only be created by the administrator. Please contact your admin to get an account.
- generic [ref=e15]:
- generic [ref=e16]:
- generic [ref=e17]: Email
- textbox "Email" [ref=e18]:
- /placeholder: your@email.com
- generic [ref=e19]:
- generic [ref=e20]: Password
- textbox "Password" [ref=e21]:
- /placeholder: ••••••••
- button "Sign In" [ref=e22] [cursor=pointer]
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,237 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Tasks" [level=1] [ref=e188]
- button "Add Task" [ref=e189] [cursor=pointer]
- generic [ref=e190]:
- generic [ref=e191]:
- paragraph [ref=e192]: "0"
- paragraph [ref=e193]: Total Tasks
- generic [ref=e194]:
- paragraph [ref=e195]: "0"
- paragraph [ref=e196]: Active
- generic [ref=e197]:
- paragraph [ref=e198]: "0"
- paragraph [ref=e199]: Completed
- generic [ref=e201]:
- textbox "Search tasks..." [ref=e202]
- combobox [ref=e203]:
- option "All Priorities" [selected]
- option "high"
- option "medium"
- option "low"
- generic [ref=e204]:
- button "all" [ref=e205] [cursor=pointer]
- button "active" [ref=e206] [cursor=pointer]
- button "completed" [ref=e207] [cursor=pointer]
- paragraph [ref=e210]: No tasks yet. Add your first task!
- button "AI Assistant" [ref=e211] [cursor=pointer]:
- img [ref=e212]
- generic [ref=e219]:
- generic [ref=e220]:
- generic [ref=e221]:
- img [ref=e223]
- generic [ref=e230]:
- heading "AI Assistant" [level=3] [ref=e231]
- paragraph [ref=e232]: Always here to help
- button [ref=e234] [cursor=pointer]:
- img [ref=e235]
- generic [ref=e239]:
- img [ref=e241]
- generic [ref=e248]:
- paragraph [ref=e249]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e250]: 04:21 PM
- generic [ref=e251]:
- generic [ref=e252]:
- textbox "Type your message..." [ref=e253]
- button [disabled]:
- img
- generic [ref=e255]:
- button "longcat icon LongCat" [ref=e257] [cursor=pointer]:
- img "longcat icon" [ref=e258]
- generic [ref=e259]: LongCat
- img [ref=e260]
- generic [ref=e262]:
- generic [ref=e263]: longcat
- link "AI settings" [ref=e264] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- heading "Add New Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Add Task" [disabled]
- generic:
- generic:
- generic:
- heading "Edit Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Save Changes" [disabled]
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,237 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Tasks" [level=1] [ref=e188]
- button "Add Task" [ref=e189] [cursor=pointer]
- generic [ref=e190]:
- generic [ref=e191]:
- paragraph [ref=e192]: "0"
- paragraph [ref=e193]: Total Tasks
- generic [ref=e194]:
- paragraph [ref=e195]: "0"
- paragraph [ref=e196]: Active
- generic [ref=e197]:
- paragraph [ref=e198]: "0"
- paragraph [ref=e199]: Completed
- generic [ref=e201]:
- textbox "Search tasks..." [ref=e202]
- combobox [ref=e203]:
- option "All Priorities" [selected]
- option "high"
- option "medium"
- option "low"
- generic [ref=e204]:
- button "all" [ref=e205] [cursor=pointer]
- button "active" [ref=e206] [cursor=pointer]
- button "completed" [ref=e207] [cursor=pointer]
- paragraph [ref=e210]: No tasks yet. Add your first task!
- button "AI Assistant" [ref=e211] [cursor=pointer]:
- img [ref=e212]
- generic [ref=e219]:
- generic [ref=e220]:
- generic [ref=e221]:
- img [ref=e223]
- generic [ref=e230]:
- heading "AI Assistant" [level=3] [ref=e231]
- paragraph [ref=e232]: Always here to help
- button [ref=e234] [cursor=pointer]:
- img [ref=e235]
- generic [ref=e239]:
- img [ref=e241]
- generic [ref=e248]:
- paragraph [ref=e249]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e250]: 04:21 PM
- generic [ref=e251]:
- generic [ref=e252]:
- textbox "Type your message..." [ref=e253]
- button [disabled]:
- img
- generic [ref=e255]:
- button "longcat icon LongCat" [ref=e257] [cursor=pointer]:
- img "longcat icon" [ref=e258]
- generic [ref=e259]: LongCat
- img [ref=e260]
- generic [ref=e262]:
- generic [ref=e263]: longcat
- link "AI settings" [ref=e264] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- heading "Add New Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Add Task" [disabled]
- generic:
- generic:
- generic:
- heading "Edit Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Save Changes" [disabled]
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,237 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Tasks" [level=1] [ref=e188]
- button "Add Task" [ref=e189] [cursor=pointer]
- generic [ref=e190]:
- generic [ref=e191]:
- paragraph [ref=e192]: "0"
- paragraph [ref=e193]: Total Tasks
- generic [ref=e194]:
- paragraph [ref=e195]: "0"
- paragraph [ref=e196]: Active
- generic [ref=e197]:
- paragraph [ref=e198]: "0"
- paragraph [ref=e199]: Completed
- generic [ref=e201]:
- textbox "Search tasks..." [ref=e202]
- combobox [ref=e203]:
- option "All Priorities" [selected]
- option "high"
- option "medium"
- option "low"
- generic [ref=e204]:
- button "all" [ref=e205] [cursor=pointer]
- button "active" [ref=e206] [cursor=pointer]
- button "completed" [ref=e207] [cursor=pointer]
- paragraph [ref=e210]: No tasks yet. Add your first task!
- button "AI Assistant" [ref=e211] [cursor=pointer]:
- img [ref=e212]
- generic [ref=e219]:
- generic [ref=e220]:
- generic [ref=e221]:
- img [ref=e223]
- generic [ref=e230]:
- heading "AI Assistant" [level=3] [ref=e231]
- paragraph [ref=e232]: Always here to help
- button [ref=e234] [cursor=pointer]:
- img [ref=e235]
- generic [ref=e239]:
- img [ref=e241]
- generic [ref=e248]:
- paragraph [ref=e249]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e250]: 04:22 PM
- generic [ref=e251]:
- generic [ref=e252]:
- textbox "Type your message..." [ref=e253]
- button [disabled]:
- img
- generic [ref=e255]:
- button "longcat icon LongCat" [ref=e257] [cursor=pointer]:
- img "longcat icon" [ref=e258]
- generic [ref=e259]: LongCat
- img [ref=e260]
- generic [ref=e262]:
- generic [ref=e263]: longcat
- link "AI settings" [ref=e264] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- heading "Add New Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Add Task" [disabled]
- generic:
- generic:
- generic:
- heading "Edit Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Save Changes" [disabled]
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,257 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Tasks" [level=1] [ref=e188]
- button "Add Task" [ref=e189] [cursor=pointer]
- generic [ref=e190]:
- generic [ref=e191]:
- paragraph [ref=e192]: "0"
- paragraph [ref=e193]: Total Tasks
- generic [ref=e194]:
- paragraph [ref=e195]: "0"
- paragraph [ref=e196]: Active
- generic [ref=e197]:
- paragraph [ref=e198]: "0"
- paragraph [ref=e199]: Completed
- generic [ref=e201]:
- textbox "Search tasks..." [ref=e202]
- combobox [ref=e203]:
- option "All Priorities" [selected]
- option "high"
- option "medium"
- option "low"
- generic [ref=e204]:
- button "all" [ref=e205] [cursor=pointer]
- button "active" [ref=e206] [cursor=pointer]
- button "completed" [ref=e207] [cursor=pointer]
- paragraph [ref=e210]: No tasks yet. Add your first task!
- button "AI Assistant" [ref=e211] [cursor=pointer]:
- img [ref=e212]
- generic [ref=e219]:
- generic [ref=e220]:
- generic [ref=e221]:
- img [ref=e223]
- generic [ref=e230]:
- heading "AI Assistant" [level=3] [ref=e231]
- paragraph [ref=e232]: Always here to help
- button [ref=e234] [cursor=pointer]:
- img [ref=e235]
- generic [ref=e239]:
- img [ref=e241]
- generic [ref=e248]:
- paragraph [ref=e249]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e250]: 04:22 PM
- generic [ref=e251]:
- generic [ref=e252]:
- textbox "Type your message..." [ref=e253]
- button [disabled]:
- img
- generic [ref=e255]:
- button "longcat icon LongCat" [ref=e257] [cursor=pointer]:
- img "longcat icon" [ref=e258]
- generic [ref=e259]: LongCat
- img [ref=e260]
- generic [ref=e262]:
- generic [ref=e263]: longcat
- link "AI settings" [ref=e264] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- heading "Add New Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Add Task" [disabled]
- generic:
- generic:
- generic:
- heading "Edit Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Save Changes" [disabled]
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
- generic [ref=e279]:
- generic [ref=e280]:
- heading "Create Workspace" [level=3] [ref=e281]
- paragraph [ref=e282]: Add a new workspace for your team or projects.
- generic [ref=e283]:
- generic [ref=e284]:
- text: Name
- textbox "Workspace name" [ref=e285]
- generic [ref=e286]:
- text: Description
- textbox "Description" [ref=e287]:
- /placeholder: Optional description
- generic [ref=e288]:
- generic [ref=e289]:
- paragraph [ref=e290]: Public workspace
- paragraph [ref=e291]: Allow all members to discover this workspace.
- switch [ref=e292] [cursor=pointer]
- generic [ref=e293]:
- button "Cancel" [ref=e294] [cursor=pointer]
- button "Create Workspace" [ref=e295] [cursor=pointer]
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,237 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Tasks" [level=1] [ref=e188]
- button "Add Task" [ref=e189] [cursor=pointer]
- generic [ref=e190]:
- generic [ref=e191]:
- paragraph [ref=e192]: "0"
- paragraph [ref=e193]: Total Tasks
- generic [ref=e194]:
- paragraph [ref=e195]: "0"
- paragraph [ref=e196]: Active
- generic [ref=e197]:
- paragraph [ref=e198]: "0"
- paragraph [ref=e199]: Completed
- generic [ref=e201]:
- textbox "Search tasks..." [ref=e202]
- combobox [ref=e203]:
- option "All Priorities" [selected]
- option "high"
- option "medium"
- option "low"
- generic [ref=e204]:
- button "all" [ref=e205] [cursor=pointer]
- button "active" [ref=e206] [cursor=pointer]
- button "completed" [ref=e207] [cursor=pointer]
- paragraph [ref=e210]: No tasks yet. Add your first task!
- button "AI Assistant" [ref=e211] [cursor=pointer]:
- img [ref=e212]
- generic [ref=e219]:
- generic [ref=e220]:
- generic [ref=e221]:
- img [ref=e223]
- generic [ref=e230]:
- heading "AI Assistant" [level=3] [ref=e231]
- paragraph [ref=e232]: Always here to help
- button [ref=e234] [cursor=pointer]:
- img [ref=e235]
- generic [ref=e239]:
- img [ref=e241]
- generic [ref=e248]:
- paragraph [ref=e249]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e250]: 04:22 PM
- generic [ref=e251]:
- generic [ref=e252]:
- textbox "Type your message..." [ref=e253]
- button [disabled]:
- img
- generic [ref=e255]:
- button "longcat icon LongCat" [ref=e257] [cursor=pointer]:
- img "longcat icon" [ref=e258]
- generic [ref=e259]: LongCat
- img [ref=e260]
- generic [ref=e262]:
- generic [ref=e263]: longcat
- link "AI settings" [ref=e264] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- heading "Add New Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Add Task" [disabled]
- generic:
- generic:
- generic:
- heading "Edit Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Save Changes" [disabled]
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,244 +0,0 @@
- generic [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [expanded] [active] [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- listbox [ref=e266]:
- option "Trackeep Workspace" [ref=e267] [cursor=pointer]:
- img [ref=e268]
- generic [ref=e271]: Trackeep Workspace
- button "Create Workspace" [ref=e274] [cursor=pointer]:
- img [ref=e275]
- generic [ref=e276]: Create Workspace
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Tasks" [level=1] [ref=e188]
- button "Add Task" [ref=e189] [cursor=pointer]
- generic [ref=e190]:
- generic [ref=e191]:
- paragraph [ref=e192]: "0"
- paragraph [ref=e193]: Total Tasks
- generic [ref=e194]:
- paragraph [ref=e195]: "0"
- paragraph [ref=e196]: Active
- generic [ref=e197]:
- paragraph [ref=e198]: "0"
- paragraph [ref=e199]: Completed
- generic [ref=e201]:
- textbox "Search tasks..." [ref=e202]
- combobox [ref=e203]:
- option "All Priorities" [selected]
- option "high"
- option "medium"
- option "low"
- generic [ref=e204]:
- button "all" [ref=e205] [cursor=pointer]
- button "active" [ref=e206] [cursor=pointer]
- button "completed" [ref=e207] [cursor=pointer]
- paragraph [ref=e210]: No tasks yet. Add your first task!
- button "AI Assistant" [ref=e211] [cursor=pointer]:
- img [ref=e212]
- generic [ref=e219]:
- generic [ref=e220]:
- generic [ref=e221]:
- img [ref=e223]
- generic [ref=e230]:
- heading "AI Assistant" [level=3] [ref=e231]
- paragraph [ref=e232]: Always here to help
- button [ref=e234] [cursor=pointer]:
- img [ref=e235]
- generic [ref=e239]:
- img [ref=e241]
- generic [ref=e248]:
- paragraph [ref=e249]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e250]: 04:22 PM
- generic [ref=e251]:
- generic [ref=e252]:
- textbox "Type your message..." [ref=e253]
- button [disabled]:
- img
- generic [ref=e255]:
- button "longcat icon LongCat" [ref=e257] [cursor=pointer]:
- img "longcat icon" [ref=e258]
- generic [ref=e259]: LongCat
- img [ref=e260]
- generic [ref=e262]:
- generic [ref=e263]: longcat
- link "AI settings" [ref=e264] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- heading "Add New Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Add Task" [disabled]
- generic:
- generic:
- generic:
- heading "Edit Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Save Changes" [disabled]
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,244 +0,0 @@
- generic [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [expanded] [active] [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- listbox [ref=e266]:
- option "Trackeep Workspace" [ref=e267] [cursor=pointer]:
- img [ref=e268]
- generic [ref=e271]: Trackeep Workspace
- button "Create Workspace" [ref=e274] [cursor=pointer]:
- img [ref=e275]
- generic [ref=e276]: Create Workspace
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Tasks" [level=1] [ref=e188]
- button "Add Task" [ref=e189] [cursor=pointer]
- generic [ref=e190]:
- generic [ref=e191]:
- paragraph [ref=e192]: "0"
- paragraph [ref=e193]: Total Tasks
- generic [ref=e194]:
- paragraph [ref=e195]: "0"
- paragraph [ref=e196]: Active
- generic [ref=e197]:
- paragraph [ref=e198]: "0"
- paragraph [ref=e199]: Completed
- generic [ref=e201]:
- textbox "Search tasks..." [ref=e202]
- combobox [ref=e203]:
- option "All Priorities" [selected]
- option "high"
- option "medium"
- option "low"
- generic [ref=e204]:
- button "all" [ref=e205] [cursor=pointer]
- button "active" [ref=e206] [cursor=pointer]
- button "completed" [ref=e207] [cursor=pointer]
- paragraph [ref=e210]: No tasks yet. Add your first task!
- button "AI Assistant" [ref=e211] [cursor=pointer]:
- img [ref=e212]
- generic [ref=e219]:
- generic [ref=e220]:
- generic [ref=e221]:
- img [ref=e223]
- generic [ref=e230]:
- heading "AI Assistant" [level=3] [ref=e231]
- paragraph [ref=e232]: Always here to help
- button [ref=e234] [cursor=pointer]:
- img [ref=e235]
- generic [ref=e239]:
- img [ref=e241]
- generic [ref=e248]:
- paragraph [ref=e249]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e250]: 04:22 PM
- generic [ref=e251]:
- generic [ref=e252]:
- textbox "Type your message..." [ref=e253]
- button [disabled]:
- img
- generic [ref=e255]:
- button "longcat icon LongCat" [ref=e257] [cursor=pointer]:
- img "longcat icon" [ref=e258]
- generic [ref=e259]: LongCat
- img [ref=e260]
- generic [ref=e262]:
- generic [ref=e263]: longcat
- link "AI settings" [ref=e264] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- heading "Add New Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Add Task" [disabled]
- generic:
- generic:
- generic:
- heading "Edit Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Save Changes" [disabled]
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,237 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Tasks" [level=1] [ref=e188]
- button "Add Task" [ref=e189] [cursor=pointer]
- generic [ref=e190]:
- generic [ref=e191]:
- paragraph [ref=e192]: "0"
- paragraph [ref=e193]: Total Tasks
- generic [ref=e194]:
- paragraph [ref=e195]: "0"
- paragraph [ref=e196]: Active
- generic [ref=e197]:
- paragraph [ref=e198]: "0"
- paragraph [ref=e199]: Completed
- generic [ref=e201]:
- textbox "Search tasks..." [ref=e202]
- combobox [ref=e203]:
- option "All Priorities" [selected]
- option "high"
- option "medium"
- option "low"
- generic [ref=e204]:
- button "all" [ref=e205] [cursor=pointer]
- button "active" [ref=e206] [cursor=pointer]
- button "completed" [ref=e207] [cursor=pointer]
- paragraph [ref=e210]: No tasks yet. Add your first task!
- button "AI Assistant" [ref=e211] [cursor=pointer]:
- img [ref=e212]
- generic [ref=e219]:
- generic [ref=e220]:
- generic [ref=e221]:
- img [ref=e223]
- generic [ref=e230]:
- heading "AI Assistant" [level=3] [ref=e231]
- paragraph [ref=e232]: Always here to help
- button [ref=e234] [cursor=pointer]:
- img [ref=e235]
- generic [ref=e239]:
- img [ref=e241]
- generic [ref=e248]:
- paragraph [ref=e249]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e250]: 04:23 PM
- generic [ref=e251]:
- generic [ref=e252]:
- textbox "Type your message..." [ref=e253]
- button [disabled]:
- img
- generic [ref=e255]:
- button "longcat icon LongCat" [ref=e257] [cursor=pointer]:
- img "longcat icon" [ref=e258]
- generic [ref=e259]: LongCat
- img [ref=e260]
- generic [ref=e262]:
- generic [ref=e263]: longcat
- link "AI settings" [ref=e264] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- heading "Add New Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Add Task" [disabled]
- generic:
- generic:
- generic:
- heading "Edit Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Save Changes" [disabled]
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,244 +0,0 @@
- generic [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [expanded] [active] [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- listbox [ref=e266]:
- option "Trackeep Workspace" [ref=e267] [cursor=pointer]:
- img [ref=e268]
- generic [ref=e271]: Trackeep Workspace
- button "Create Workspace" [ref=e274] [cursor=pointer]:
- img [ref=e275]
- generic [ref=e276]: Create Workspace
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Tasks" [level=1] [ref=e188]
- button "Add Task" [ref=e189] [cursor=pointer]
- generic [ref=e190]:
- generic [ref=e191]:
- paragraph [ref=e192]: "0"
- paragraph [ref=e193]: Total Tasks
- generic [ref=e194]:
- paragraph [ref=e195]: "0"
- paragraph [ref=e196]: Active
- generic [ref=e197]:
- paragraph [ref=e198]: "0"
- paragraph [ref=e199]: Completed
- generic [ref=e201]:
- textbox "Search tasks..." [ref=e202]
- combobox [ref=e203]:
- option "All Priorities" [selected]
- option "high"
- option "medium"
- option "low"
- generic [ref=e204]:
- button "all" [ref=e205] [cursor=pointer]
- button "active" [ref=e206] [cursor=pointer]
- button "completed" [ref=e207] [cursor=pointer]
- paragraph [ref=e210]: No tasks yet. Add your first task!
- button "AI Assistant" [ref=e211] [cursor=pointer]:
- img [ref=e212]
- generic [ref=e219]:
- generic [ref=e220]:
- generic [ref=e221]:
- img [ref=e223]
- generic [ref=e230]:
- heading "AI Assistant" [level=3] [ref=e231]
- paragraph [ref=e232]: Always here to help
- button [ref=e234] [cursor=pointer]:
- img [ref=e235]
- generic [ref=e239]:
- img [ref=e241]
- generic [ref=e248]:
- paragraph [ref=e249]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e250]: 04:23 PM
- generic [ref=e251]:
- generic [ref=e252]:
- textbox "Type your message..." [ref=e253]
- button [disabled]:
- img
- generic [ref=e255]:
- button "longcat icon LongCat" [ref=e257] [cursor=pointer]:
- img "longcat icon" [ref=e258]
- generic [ref=e259]: LongCat
- img [ref=e260]
- generic [ref=e262]:
- generic [ref=e263]: longcat
- link "AI settings" [ref=e264] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- heading "Add New Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Add Task" [disabled]
- generic:
- generic:
- generic:
- heading "Edit Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Save Changes" [disabled]
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,257 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Tasks" [level=1] [ref=e188]
- button "Add Task" [ref=e189] [cursor=pointer]
- generic [ref=e190]:
- generic [ref=e191]:
- paragraph [ref=e192]: "0"
- paragraph [ref=e193]: Total Tasks
- generic [ref=e194]:
- paragraph [ref=e195]: "0"
- paragraph [ref=e196]: Active
- generic [ref=e197]:
- paragraph [ref=e198]: "0"
- paragraph [ref=e199]: Completed
- generic [ref=e201]:
- textbox "Search tasks..." [ref=e202]
- combobox [ref=e203]:
- option "All Priorities" [selected]
- option "high"
- option "medium"
- option "low"
- generic [ref=e204]:
- button "all" [ref=e205] [cursor=pointer]
- button "active" [ref=e206] [cursor=pointer]
- button "completed" [ref=e207] [cursor=pointer]
- paragraph [ref=e210]: No tasks yet. Add your first task!
- button "AI Assistant" [ref=e211] [cursor=pointer]:
- img [ref=e212]
- generic [ref=e219]:
- generic [ref=e220]:
- generic [ref=e221]:
- img [ref=e223]
- generic [ref=e230]:
- heading "AI Assistant" [level=3] [ref=e231]
- paragraph [ref=e232]: Always here to help
- button [ref=e234] [cursor=pointer]:
- img [ref=e235]
- generic [ref=e239]:
- img [ref=e241]
- generic [ref=e248]:
- paragraph [ref=e249]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e250]: 04:23 PM
- generic [ref=e251]:
- generic [ref=e252]:
- textbox "Type your message..." [ref=e253]
- button [disabled]:
- img
- generic [ref=e255]:
- button "longcat icon LongCat" [ref=e257] [cursor=pointer]:
- img "longcat icon" [ref=e258]
- generic [ref=e259]: LongCat
- img [ref=e260]
- generic [ref=e262]:
- generic [ref=e263]: longcat
- link "AI settings" [ref=e264] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- heading "Add New Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Add Task" [disabled]
- generic:
- generic:
- generic:
- heading "Edit Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Save Changes" [disabled]
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
- generic [ref=e279]:
- generic [ref=e280]:
- heading "Create Workspace" [level=3] [ref=e281]
- paragraph [ref=e282]: Add a new workspace for your team or projects.
- generic [ref=e283]:
- generic [ref=e284]:
- text: Name
- textbox "Workspace name" [ref=e285]
- generic [ref=e286]:
- text: Description
- textbox "Description" [ref=e287]:
- /placeholder: Optional description
- generic [ref=e288]:
- generic [ref=e289]:
- paragraph [ref=e290]: Public workspace
- paragraph [ref=e291]: Allow all members to discover this workspace.
- switch [ref=e292] [cursor=pointer]
- generic [ref=e293]:
- button "Cancel" [ref=e294] [cursor=pointer]
- button "Create Workspace" [ref=e295] [cursor=pointer]
@@ -1,257 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Tasks" [level=1] [ref=e188]
- button "Add Task" [ref=e189] [cursor=pointer]
- generic [ref=e190]:
- generic [ref=e191]:
- paragraph [ref=e192]: "0"
- paragraph [ref=e193]: Total Tasks
- generic [ref=e194]:
- paragraph [ref=e195]: "0"
- paragraph [ref=e196]: Active
- generic [ref=e197]:
- paragraph [ref=e198]: "0"
- paragraph [ref=e199]: Completed
- generic [ref=e201]:
- textbox "Search tasks..." [ref=e202]
- combobox [ref=e203]:
- option "All Priorities" [selected]
- option "high"
- option "medium"
- option "low"
- generic [ref=e204]:
- button "all" [ref=e205] [cursor=pointer]
- button "active" [ref=e206] [cursor=pointer]
- button "completed" [ref=e207] [cursor=pointer]
- paragraph [ref=e210]: No tasks yet. Add your first task!
- button "AI Assistant" [ref=e211] [cursor=pointer]:
- img [ref=e212]
- generic [ref=e219]:
- generic [ref=e220]:
- generic [ref=e221]:
- img [ref=e223]
- generic [ref=e230]:
- heading "AI Assistant" [level=3] [ref=e231]
- paragraph [ref=e232]: Always here to help
- button [ref=e234] [cursor=pointer]:
- img [ref=e235]
- generic [ref=e239]:
- img [ref=e241]
- generic [ref=e248]:
- paragraph [ref=e249]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e250]: 04:23 PM
- generic [ref=e251]:
- generic [ref=e252]:
- textbox "Type your message..." [ref=e253]
- button [disabled]:
- img
- generic [ref=e255]:
- button "longcat icon LongCat" [ref=e257] [cursor=pointer]:
- img "longcat icon" [ref=e258]
- generic [ref=e259]: LongCat
- img [ref=e260]
- generic [ref=e262]:
- generic [ref=e263]: longcat
- link "AI settings" [ref=e264] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- heading "Add New Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Add Task" [disabled]
- generic:
- generic:
- generic:
- heading "Edit Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Save Changes" [disabled]
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
- generic [ref=e279]:
- generic [ref=e280]:
- heading "Create Workspace" [level=3] [ref=e281]
- paragraph [ref=e282]: Add a new workspace for your team or projects.
- generic [ref=e283]:
- generic [ref=e284]:
- text: Name
- textbox "Workspace name" [ref=e285]
- generic [ref=e286]:
- text: Description
- textbox "Description" [ref=e287]:
- /placeholder: Optional description
- generic [ref=e288]:
- generic [ref=e289]:
- paragraph [ref=e290]: Public workspace
- paragraph [ref=e291]: Allow all members to discover this workspace.
- switch [ref=e292] [cursor=pointer]
- generic [ref=e293]:
- button "Cancel" [ref=e294] [cursor=pointer]
- button "Create Workspace" [ref=e295] [cursor=pointer]
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,237 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Tasks" [level=1] [ref=e188]
- button "Add Task" [ref=e189] [cursor=pointer]
- generic [ref=e190]:
- generic [ref=e191]:
- paragraph [ref=e192]: "0"
- paragraph [ref=e193]: Total Tasks
- generic [ref=e194]:
- paragraph [ref=e195]: "0"
- paragraph [ref=e196]: Active
- generic [ref=e197]:
- paragraph [ref=e198]: "0"
- paragraph [ref=e199]: Completed
- generic [ref=e201]:
- textbox "Search tasks..." [ref=e202]
- combobox [ref=e203]:
- option "All Priorities" [selected]
- option "high"
- option "medium"
- option "low"
- generic [ref=e204]:
- button "all" [ref=e205] [cursor=pointer]
- button "active" [ref=e206] [cursor=pointer]
- button "completed" [ref=e207] [cursor=pointer]
- paragraph [ref=e210]: No tasks yet. Add your first task!
- button "AI Assistant" [ref=e211] [cursor=pointer]:
- img [ref=e212]
- generic [ref=e219]:
- generic [ref=e220]:
- generic [ref=e221]:
- img [ref=e223]
- generic [ref=e230]:
- heading "AI Assistant" [level=3] [ref=e231]
- paragraph [ref=e232]: Always here to help
- button [ref=e234] [cursor=pointer]:
- img [ref=e235]
- generic [ref=e239]:
- img [ref=e241]
- generic [ref=e248]:
- paragraph [ref=e249]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e250]: 04:23 PM
- generic [ref=e251]:
- generic [ref=e252]:
- textbox "Type your message..." [ref=e253]
- button [disabled]:
- img
- generic [ref=e255]:
- button "longcat icon LongCat" [ref=e257] [cursor=pointer]:
- img "longcat icon" [ref=e258]
- generic [ref=e259]: LongCat
- img [ref=e260]
- generic [ref=e262]:
- generic [ref=e263]: longcat
- link "AI settings" [ref=e264] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- heading "Add New Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Add Task" [disabled]
- generic:
- generic:
- generic:
- heading "Edit Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Save Changes" [disabled]
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,263 +0,0 @@
- generic [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- generic [ref=e178]:
- button "AU" [active] [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- generic [ref=e267]:
- generic [ref=e269]:
- generic [ref=e270]: AU
- generic [ref=e271]:
- paragraph [ref=e272]: Admin User
- paragraph [ref=e273]: admin@trackeep.com
- generic [ref=e275]:
- generic [ref=e276]:
- paragraph [ref=e277]: "0"
- paragraph [ref=e278]: Bookmarks
- generic [ref=e279]:
- paragraph [ref=e280]: "0"
- paragraph [ref=e281]: Tasks
- button "Profile" [ref=e282] [cursor=pointer]:
- img [ref=e283]
- text: Profile
- button "Statistics" [ref=e286] [cursor=pointer]:
- img [ref=e287]
- text: Statistics
- button "Settings" [ref=e289] [cursor=pointer]:
- img [ref=e290]
- text: Settings
- button "Logout" [ref=e294] [cursor=pointer]:
- img [ref=e295]
- text: Logout
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Tasks" [level=1] [ref=e188]
- button "Add Task" [ref=e189] [cursor=pointer]
- generic [ref=e190]:
- generic [ref=e191]:
- paragraph [ref=e192]: "0"
- paragraph [ref=e193]: Total Tasks
- generic [ref=e194]:
- paragraph [ref=e195]: "0"
- paragraph [ref=e196]: Active
- generic [ref=e197]:
- paragraph [ref=e198]: "0"
- paragraph [ref=e199]: Completed
- generic [ref=e201]:
- textbox "Search tasks..." [ref=e202]
- combobox [ref=e203]:
- option "All Priorities" [selected]
- option "high"
- option "medium"
- option "low"
- generic [ref=e204]:
- button "all" [ref=e205] [cursor=pointer]
- button "active" [ref=e206] [cursor=pointer]
- button "completed" [ref=e207] [cursor=pointer]
- paragraph [ref=e210]: No tasks yet. Add your first task!
- button "AI Assistant" [ref=e211] [cursor=pointer]:
- img [ref=e212]
- generic [ref=e219]:
- generic [ref=e220]:
- generic [ref=e221]:
- img [ref=e223]
- generic [ref=e230]:
- heading "AI Assistant" [level=3] [ref=e231]
- paragraph [ref=e232]: Always here to help
- button [ref=e234] [cursor=pointer]:
- img [ref=e235]
- generic [ref=e239]:
- img [ref=e241]
- generic [ref=e248]:
- paragraph [ref=e249]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e250]: 04:23 PM
- generic [ref=e251]:
- generic [ref=e252]:
- textbox "Type your message..." [ref=e253]
- button [disabled]:
- img
- generic [ref=e255]:
- button "longcat icon LongCat" [ref=e257] [cursor=pointer]:
- img "longcat icon" [ref=e258]
- generic [ref=e259]: LongCat
- img [ref=e260]
- generic [ref=e262]:
- generic [ref=e263]: longcat
- link "AI settings" [ref=e264] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- heading "Add New Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Add Task" [disabled]
- generic:
- generic:
- generic:
- heading "Edit Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Save Changes" [disabled]
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,263 +0,0 @@
- generic [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- generic [ref=e178]:
- button "AU" [active] [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- generic [ref=e267]:
- generic [ref=e269]:
- generic [ref=e270]: AU
- generic [ref=e271]:
- paragraph [ref=e272]: Admin User
- paragraph [ref=e273]: admin@trackeep.com
- generic [ref=e275]:
- generic [ref=e276]:
- paragraph [ref=e277]: "0"
- paragraph [ref=e278]: Bookmarks
- generic [ref=e279]:
- paragraph [ref=e280]: "0"
- paragraph [ref=e281]: Tasks
- button "Profile" [ref=e282] [cursor=pointer]:
- img [ref=e283]
- text: Profile
- button "Statistics" [ref=e286] [cursor=pointer]:
- img [ref=e287]
- text: Statistics
- button "Settings" [ref=e289] [cursor=pointer]:
- img [ref=e290]
- text: Settings
- button "Logout" [ref=e294] [cursor=pointer]:
- img [ref=e295]
- text: Logout
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Tasks" [level=1] [ref=e188]
- button "Add Task" [ref=e189] [cursor=pointer]
- generic [ref=e190]:
- generic [ref=e191]:
- paragraph [ref=e192]: "0"
- paragraph [ref=e193]: Total Tasks
- generic [ref=e194]:
- paragraph [ref=e195]: "0"
- paragraph [ref=e196]: Active
- generic [ref=e197]:
- paragraph [ref=e198]: "0"
- paragraph [ref=e199]: Completed
- generic [ref=e201]:
- textbox "Search tasks..." [ref=e202]
- combobox [ref=e203]:
- option "All Priorities" [selected]
- option "high"
- option "medium"
- option "low"
- generic [ref=e204]:
- button "all" [ref=e205] [cursor=pointer]
- button "active" [ref=e206] [cursor=pointer]
- button "completed" [ref=e207] [cursor=pointer]
- paragraph [ref=e210]: No tasks yet. Add your first task!
- button "AI Assistant" [ref=e211] [cursor=pointer]:
- img [ref=e212]
- generic [ref=e219]:
- generic [ref=e220]:
- generic [ref=e221]:
- img [ref=e223]
- generic [ref=e230]:
- heading "AI Assistant" [level=3] [ref=e231]
- paragraph [ref=e232]: Always here to help
- button [ref=e234] [cursor=pointer]:
- img [ref=e235]
- generic [ref=e239]:
- img [ref=e241]
- generic [ref=e248]:
- paragraph [ref=e249]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e250]: 04:23 PM
- generic [ref=e251]:
- generic [ref=e252]:
- textbox "Type your message..." [ref=e253]
- button [disabled]:
- img
- generic [ref=e255]:
- button "longcat icon LongCat" [ref=e257] [cursor=pointer]:
- img "longcat icon" [ref=e258]
- generic [ref=e259]: LongCat
- img [ref=e260]
- generic [ref=e262]:
- generic [ref=e263]: longcat
- link "AI settings" [ref=e264] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- heading "Add New Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Add Task" [disabled]
- generic:
- generic:
- generic:
- heading "Edit Task" [level=3]
- button:
- img
- generic:
- textbox "Task title *"
- textbox "Description (optional)"
- generic:
- combobox:
- option "Low Priority"
- option "Medium Priority" [selected]
- option "High Priority"
- generic:
- button "Due date (optional)":
- generic: Due date (optional)
- img
- generic:
- button "Cancel"
- button "Save Changes" [disabled]
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,197 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Files" [level=1] [ref=e188]
- button "Upload File" [ref=e189] [cursor=pointer]:
- img [ref=e190]
- text: Upload File
- generic [ref=e194]:
- textbox "Search files..." [ref=e195]
- combobox [ref=e196]:
- option "All Tags" [selected]
- paragraph [ref=e198]: No files uploaded yet. Upload your first file!
- button "AI Assistant" [ref=e199] [cursor=pointer]:
- img [ref=e200]
- generic [ref=e207]:
- generic [ref=e208]:
- generic [ref=e209]:
- img [ref=e211]
- generic [ref=e218]:
- heading "AI Assistant" [level=3] [ref=e219]
- paragraph [ref=e220]: Always here to help
- button [ref=e222] [cursor=pointer]:
- img [ref=e223]
- generic [ref=e227]:
- img [ref=e229]
- generic [ref=e236]:
- paragraph [ref=e237]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e238]: 04:24 PM
- generic [ref=e239]:
- generic [ref=e240]:
- textbox "Type your message..." [ref=e241]
- button [disabled]:
- img
- generic [ref=e243]:
- button "longcat icon LongCat" [ref=e245] [cursor=pointer]:
- img "longcat icon" [ref=e246]
- generic [ref=e247]: LongCat
- img [ref=e248]
- generic [ref=e250]:
- generic [ref=e251]: longcat
- link "AI settings" [ref=e252] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- generic:
- heading [level=3]
- generic: Unknown size
- button:
- img
- generic:
- generic: Unknown file type
- generic:
- button "Download":
- img
- text: Download
- button "Open":
- img
- text: Open
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,197 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Files" [level=1] [ref=e188]
- button "Upload File" [ref=e189] [cursor=pointer]:
- img [ref=e190]
- text: Upload File
- generic [ref=e194]:
- textbox "Search files..." [ref=e195]
- combobox [ref=e196]:
- option "All Tags" [selected]
- paragraph [ref=e198]: No files uploaded yet. Upload your first file!
- button "AI Assistant" [ref=e199] [cursor=pointer]:
- img [ref=e200]
- generic [ref=e207]:
- generic [ref=e208]:
- generic [ref=e209]:
- img [ref=e211]
- generic [ref=e218]:
- heading "AI Assistant" [level=3] [ref=e219]
- paragraph [ref=e220]: Always here to help
- button [ref=e222] [cursor=pointer]:
- img [ref=e223]
- generic [ref=e227]:
- img [ref=e229]
- generic [ref=e236]:
- paragraph [ref=e237]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e238]: 04:24 PM
- generic [ref=e239]:
- generic [ref=e240]:
- textbox "Type your message..." [ref=e241]
- button [disabled]:
- img
- generic [ref=e243]:
- button "longcat icon LongCat" [ref=e245] [cursor=pointer]:
- img "longcat icon" [ref=e246]
- generic [ref=e247]: LongCat
- img [ref=e248]
- generic [ref=e250]:
- generic [ref=e251]: longcat
- link "AI settings" [ref=e252] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- generic:
- heading [level=3]
- generic: Unknown size
- button:
- img
- generic:
- generic: Unknown file type
- generic:
- button "Download":
- img
- text: Download
- button "Open":
- img
- text: Open
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,197 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Files" [level=1] [ref=e188]
- button "Upload File" [ref=e189] [cursor=pointer]:
- img [ref=e190]
- text: Upload File
- generic [ref=e194]:
- textbox "Search files..." [ref=e195]
- combobox [ref=e196]:
- option "All Tags" [selected]
- paragraph [ref=e198]: No files uploaded yet. Upload your first file!
- button "AI Assistant" [ref=e199] [cursor=pointer]:
- img [ref=e200]
- generic [ref=e207]:
- generic [ref=e208]:
- generic [ref=e209]:
- img [ref=e211]
- generic [ref=e218]:
- heading "AI Assistant" [level=3] [ref=e219]
- paragraph [ref=e220]: Always here to help
- button [ref=e222] [cursor=pointer]:
- img [ref=e223]
- generic [ref=e227]:
- img [ref=e229]
- generic [ref=e236]:
- paragraph [ref=e237]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e238]: 04:24 PM
- generic [ref=e239]:
- generic [ref=e240]:
- textbox "Type your message..." [ref=e241]
- button [disabled]:
- img
- generic [ref=e243]:
- button "longcat icon LongCat" [ref=e245] [cursor=pointer]:
- img "longcat icon" [ref=e246]
- generic [ref=e247]: LongCat
- img [ref=e248]
- generic [ref=e250]:
- generic [ref=e251]: longcat
- link "AI settings" [ref=e252] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- generic:
- heading [level=3]
- generic: Unknown size
- button:
- img
- generic:
- generic: Unknown file type
- generic:
- button "Download":
- img
- text: Download
- button "Open":
- img
- text: Open
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,197 +0,0 @@
- generic [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Files" [level=1] [ref=e188]
- button "Upload File" [active] [ref=e189] [cursor=pointer]:
- img [ref=e190]
- text: Upload File
- generic [ref=e194]:
- textbox "Search files..." [ref=e195]
- combobox [ref=e196]:
- option "All Tags" [selected]
- paragraph [ref=e198]: No files uploaded yet. Upload your first file!
- button "AI Assistant" [ref=e199] [cursor=pointer]:
- img [ref=e200]
- generic [ref=e207]:
- generic [ref=e208]:
- generic [ref=e209]:
- img [ref=e211]
- generic [ref=e218]:
- heading "AI Assistant" [level=3] [ref=e219]
- paragraph [ref=e220]: Always here to help
- button [ref=e222] [cursor=pointer]:
- img [ref=e223]
- generic [ref=e227]:
- img [ref=e229]
- generic [ref=e236]:
- paragraph [ref=e237]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e238]: 04:24 PM
- generic [ref=e239]:
- generic [ref=e240]:
- textbox "Type your message..." [ref=e241]
- button [disabled]:
- img
- generic [ref=e243]:
- button "longcat icon LongCat" [ref=e245] [cursor=pointer]:
- img "longcat icon" [ref=e246]
- generic [ref=e247]: LongCat
- img [ref=e248]
- generic [ref=e250]:
- generic [ref=e251]: longcat
- link "AI settings" [ref=e252] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- generic:
- heading [level=3]
- generic: Unknown size
- button:
- img
- generic:
- generic: Unknown file type
- generic:
- button "Download":
- img
- text: Download
- button "Open":
- img
- text: Open
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,197 +0,0 @@
- generic [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Files" [level=1] [ref=e188]
- button "Upload File" [active] [ref=e189] [cursor=pointer]:
- img [ref=e190]
- text: Upload File
- generic [ref=e194]:
- textbox "Search files..." [ref=e195]
- combobox [ref=e196]:
- option "All Tags" [selected]
- paragraph [ref=e198]: No files uploaded yet. Upload your first file!
- button "AI Assistant" [ref=e199] [cursor=pointer]:
- img [ref=e200]
- generic [ref=e207]:
- generic [ref=e208]:
- generic [ref=e209]:
- img [ref=e211]
- generic [ref=e218]:
- heading "AI Assistant" [level=3] [ref=e219]
- paragraph [ref=e220]: Always here to help
- button [ref=e222] [cursor=pointer]:
- img [ref=e223]
- generic [ref=e227]:
- img [ref=e229]
- generic [ref=e236]:
- paragraph [ref=e237]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e238]: 04:24 PM
- generic [ref=e239]:
- generic [ref=e240]:
- textbox "Type your message..." [ref=e241]
- button [disabled]:
- img
- generic [ref=e243]:
- button "longcat icon LongCat" [ref=e245] [cursor=pointer]:
- img "longcat icon" [ref=e246]
- generic [ref=e247]: LongCat
- img [ref=e248]
- generic [ref=e250]:
- generic [ref=e251]: longcat
- link "AI settings" [ref=e252] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- generic:
- heading [level=3]
- generic: Unknown size
- button:
- img
- generic:
- generic: Unknown file type
- generic:
- button "Download":
- img
- text: Download
- button "Open":
- img
- text: Open
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,197 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Files" [level=1] [ref=e188]
- button "Upload File" [ref=e189] [cursor=pointer]:
- img [ref=e190]
- text: Upload File
- generic [ref=e194]:
- textbox "Search files..." [ref=e195]
- combobox [ref=e196]:
- option "All Tags" [selected]
- paragraph [ref=e198]: No files uploaded yet. Upload your first file!
- button "AI Assistant" [ref=e199] [cursor=pointer]:
- img [ref=e200]
- generic [ref=e207]:
- generic [ref=e208]:
- generic [ref=e209]:
- img [ref=e211]
- generic [ref=e218]:
- heading "AI Assistant" [level=3] [ref=e219]
- paragraph [ref=e220]: Always here to help
- button [ref=e222] [cursor=pointer]:
- img [ref=e223]
- generic [ref=e227]:
- img [ref=e229]
- generic [ref=e236]:
- paragraph [ref=e237]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e238]: 04:25 PM
- generic [ref=e239]:
- generic [ref=e240]:
- textbox "Type your message..." [ref=e241]
- button [disabled]:
- img
- generic [ref=e243]:
- button "longcat icon LongCat" [ref=e245] [cursor=pointer]:
- img "longcat icon" [ref=e246]
- generic [ref=e247]: LongCat
- img [ref=e248]
- generic [ref=e250]:
- generic [ref=e251]: longcat
- link "AI settings" [ref=e252] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- generic:
- heading [level=3]
- generic: Unknown size
- button:
- img
- generic:
- generic: Unknown file type
- generic:
- button "Download":
- img
- text: Download
- button "Open":
- img
- text: Open
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,197 +0,0 @@
- generic [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Files" [level=1] [ref=e188]
- button "Upload File" [active] [ref=e189] [cursor=pointer]:
- img [ref=e190]
- text: Upload File
- generic [ref=e194]:
- textbox "Search files..." [ref=e195]
- combobox [ref=e196]:
- option "All Tags" [selected]
- paragraph [ref=e198]: No files uploaded yet. Upload your first file!
- button "AI Assistant" [ref=e199] [cursor=pointer]:
- img [ref=e200]
- generic [ref=e207]:
- generic [ref=e208]:
- generic [ref=e209]:
- img [ref=e211]
- generic [ref=e218]:
- heading "AI Assistant" [level=3] [ref=e219]
- paragraph [ref=e220]: Always here to help
- button [ref=e222] [cursor=pointer]:
- img [ref=e223]
- generic [ref=e227]:
- img [ref=e229]
- generic [ref=e236]:
- paragraph [ref=e237]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e238]: 04:25 PM
- generic [ref=e239]:
- generic [ref=e240]:
- textbox "Type your message..." [ref=e241]
- button [disabled]:
- img
- generic [ref=e243]:
- button "longcat icon LongCat" [ref=e245] [cursor=pointer]:
- img "longcat icon" [ref=e246]
- generic [ref=e247]: LongCat
- img [ref=e248]
- generic [ref=e250]:
- generic [ref=e251]: longcat
- link "AI settings" [ref=e252] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- generic:
- heading [level=3]
- generic: Unknown size
- button:
- img
- generic:
- generic: Unknown file type
- generic:
- button "Download":
- img
- text: Download
- button "Open":
- img
- text: Open
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,197 +0,0 @@
- generic [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Files" [level=1] [ref=e188]
- button "Upload File" [active] [ref=e189] [cursor=pointer]:
- img [ref=e190]
- text: Upload File
- generic [ref=e194]:
- textbox "Search files..." [ref=e195]
- combobox [ref=e196]:
- option "All Tags" [selected]
- paragraph [ref=e198]: No files uploaded yet. Upload your first file!
- button "AI Assistant" [ref=e199] [cursor=pointer]:
- img [ref=e200]
- generic [ref=e207]:
- generic [ref=e208]:
- generic [ref=e209]:
- img [ref=e211]
- generic [ref=e218]:
- heading "AI Assistant" [level=3] [ref=e219]
- paragraph [ref=e220]: Always here to help
- button [ref=e222] [cursor=pointer]:
- img [ref=e223]
- generic [ref=e227]:
- img [ref=e229]
- generic [ref=e236]:
- paragraph [ref=e237]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e238]: 04:25 PM
- generic [ref=e239]:
- generic [ref=e240]:
- textbox "Type your message..." [ref=e241]
- button [disabled]:
- img
- generic [ref=e243]:
- button "longcat icon LongCat" [ref=e245] [cursor=pointer]:
- img "longcat icon" [ref=e246]
- generic [ref=e247]: LongCat
- img [ref=e248]
- generic [ref=e250]:
- generic [ref=e251]: longcat
- link "AI settings" [ref=e252] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- generic:
- heading [level=3]
- generic: Unknown size
- button:
- img
- generic:
- generic: Unknown file type
- generic:
- button "Download":
- img
- text: Download
- button "Open":
- img
- text: Open
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,14 +0,0 @@
- generic [ref=e5]:
- generic [ref=e7]:
- img "Trackeep Logo" [ref=e10]
- heading "Authentication Required" [level=1] [ref=e11]
- paragraph [ref=e12]: Please sign in to access Trackeep
- generic [ref=e13]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e19]:
- heading "Authentication Required" [level=3] [ref=e20]
- paragraph [ref=e21]: You need to be authenticated to access this page. Please sign in or create an account to continue.
- generic [ref=e22]:
- button "Sign In" [ref=e23] [cursor=pointer]
- button "Create Account" [ref=e24] [cursor=pointer]
@@ -1,197 +0,0 @@
- generic [active] [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Files" [level=1] [ref=e188]
- button "Upload File" [ref=e189] [cursor=pointer]:
- img [ref=e190]
- text: Upload File
- generic [ref=e194]:
- textbox "Search files..." [ref=e195]
- combobox [ref=e196]:
- option "All Tags" [selected]
- paragraph [ref=e198]: No files uploaded yet. Upload your first file!
- button "AI Assistant" [ref=e199] [cursor=pointer]:
- img [ref=e200]
- generic [ref=e207]:
- generic [ref=e208]:
- generic [ref=e209]:
- img [ref=e211]
- generic [ref=e218]:
- heading "AI Assistant" [level=3] [ref=e219]
- paragraph [ref=e220]: Always here to help
- button [ref=e222] [cursor=pointer]:
- img [ref=e223]
- generic [ref=e227]:
- img [ref=e229]
- generic [ref=e236]:
- paragraph [ref=e237]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e238]: 04:26 PM
- generic [ref=e239]:
- generic [ref=e240]:
- textbox "Type your message..." [ref=e241]
- button [disabled]:
- img
- generic [ref=e243]:
- button "longcat icon LongCat" [ref=e245] [cursor=pointer]:
- img "longcat icon" [ref=e246]
- generic [ref=e247]: LongCat
- img [ref=e248]
- generic [ref=e250]:
- generic [ref=e251]: longcat
- link "AI settings" [ref=e252] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- generic:
- heading [level=3]
- generic: Unknown size
- button:
- img
- generic:
- generic: Unknown file type
- generic:
- button "Download":
- img
- text: Download
- button "Open":
- img
- text: Open
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
@@ -1,197 +0,0 @@
- generic [ref=e1]:
- generic [ref=e4]:
- generic [ref=e7]:
- link "Trackeep Logo Trackeep" [ref=e9] [cursor=pointer]:
- /url: /app
- img "Trackeep Logo" [ref=e10]
- generic [ref=e11]: Trackeep
- group [ref=e13]:
- button "Trackeep Workspace" [ref=e14] [cursor=pointer]:
- generic [ref=e15]:
- img [ref=e17]
- generic [ref=e20]: Trackeep Workspace
- img [ref=e22]
- navigation [ref=e24]:
- link "Home" [ref=e25] [cursor=pointer]:
- /url: /app
- generic [ref=e26]:
- img [ref=e27]
- generic [ref=e31]: Home
- link "Bookmarks" [ref=e33] [cursor=pointer]:
- /url: /app/bookmarks
- generic [ref=e34]:
- img [ref=e35]
- generic [ref=e37]: Bookmarks
- link "Tasks" [ref=e39] [cursor=pointer]:
- /url: /app/tasks
- generic [ref=e40]:
- img [ref=e41]
- generic [ref=e44]: Tasks
- link "Time Tracking" [ref=e46] [cursor=pointer]:
- /url: /app/time-tracking
- generic [ref=e47]:
- img [ref=e48]
- generic [ref=e51]: Time Tracking
- link "Calendar" [ref=e53] [cursor=pointer]:
- /url: /app/calendar
- generic [ref=e54]:
- img [ref=e55]
- generic [ref=e57]: Calendar
- link "Files" [ref=e59] [cursor=pointer]:
- /url: /app/files
- generic [ref=e60]:
- img [ref=e61]
- generic [ref=e63]: Files
- link "Notes" [ref=e65] [cursor=pointer]:
- /url: /app/notes
- generic [ref=e66]:
- img [ref=e67]
- generic [ref=e69]: Notes
- link "Messages" [ref=e71] [cursor=pointer]:
- /url: /app/messages
- generic [ref=e72]:
- img [ref=e73]
- generic [ref=e75]: Messages
- link "YouTube" [ref=e77] [cursor=pointer]:
- /url: /app/youtube
- generic [ref=e78]:
- img [ref=e79]
- generic [ref=e82]: YouTube
- link "Members" [ref=e84] [cursor=pointer]:
- /url: /app/members
- generic [ref=e85]:
- img [ref=e86]
- generic [ref=e91]: Members
- link "Learning" [ref=e93] [cursor=pointer]:
- /url: /app/learning-paths
- generic [ref=e94]:
- img [ref=e95]
- generic [ref=e98]: Learning
- link "Stats" [ref=e100] [cursor=pointer]:
- /url: /app/stats
- generic [ref=e101]:
- img [ref=e102]
- generic [ref=e104]: Stats
- link "GitHub" [ref=e106] [cursor=pointer]:
- /url: /app/github
- generic [ref=e107]:
- img [ref=e108]
- generic [ref=e110]: GitHub
- link "AI Assistant" [ref=e112] [cursor=pointer]:
- /url: /app/chat
- generic [ref=e113]:
- img [ref=e114]
- generic [ref=e121]: AI Assistant
- generic [ref=e124]:
- generic [ref=e125]: Version 1.0.0
- button "Update Failed" [ref=e126] [cursor=pointer]:
- generic [ref=e127]:
- img [ref=e128]
- generic [ref=e130]: Update Failed
- navigation [ref=e132]:
- link "Removed stuff" [ref=e133] [cursor=pointer]:
- /url: /app/removed-stuff
- generic [ref=e134]:
- img [ref=e135]
- generic [ref=e138]: Removed stuff
- link "Settings" [ref=e140] [cursor=pointer]:
- /url: /app/settings
- generic [ref=e141]:
- img [ref=e142]
- generic [ref=e145]: Settings
- button "Logout" [ref=e147] [cursor=pointer]:
- generic [ref=e148]:
- img [ref=e149]
- generic [ref=e153]: Logout
- generic [ref=e155]:
- generic [ref=e156]:
- generic [ref=e157]:
- button [ref=e158] [cursor=pointer]:
- img [ref=e159]
- button "Quick search" [ref=e160] [cursor=pointer]:
- img [ref=e161]
- text: Quick search
- generic [ref=e164]:
- button "Import a document" [ref=e165] [cursor=pointer]:
- img [ref=e166]
- text: Import a document
- button [ref=e170] [cursor=pointer]:
- img [ref=e171]
- img [ref=e176]
- button "AU" [ref=e180] [cursor=pointer]:
- generic [ref=e181]: AU
- img [ref=e182]
- main [ref=e184]:
- generic [ref=e186]:
- generic [ref=e187]:
- heading "Files" [level=1] [ref=e188]
- button "Upload File" [active] [ref=e189] [cursor=pointer]:
- img [ref=e190]
- text: Upload File
- generic [ref=e194]:
- textbox "Search files..." [ref=e195]
- combobox [ref=e196]:
- option "All Tags" [selected]
- paragraph [ref=e198]: No files uploaded yet. Upload your first file!
- button "AI Assistant" [ref=e199] [cursor=pointer]:
- img [ref=e200]
- generic [ref=e207]:
- generic [ref=e208]:
- generic [ref=e209]:
- img [ref=e211]
- generic [ref=e218]:
- heading "AI Assistant" [level=3] [ref=e219]
- paragraph [ref=e220]: Always here to help
- button [ref=e222] [cursor=pointer]:
- img [ref=e223]
- generic [ref=e227]:
- img [ref=e229]
- generic [ref=e236]:
- paragraph [ref=e237]: Hello! I'm your AI assistant. How can I help you today?
- paragraph [ref=e238]: 04:26 PM
- generic [ref=e239]:
- generic [ref=e240]:
- textbox "Type your message..." [ref=e241]
- button [disabled]:
- img
- generic [ref=e243]:
- button "longcat icon LongCat" [ref=e245] [cursor=pointer]:
- img "longcat icon" [ref=e246]
- generic [ref=e247]: LongCat
- img [ref=e248]
- generic [ref=e250]:
- generic [ref=e251]: longcat
- link "AI settings" [ref=e252] [cursor=pointer]:
- /url: /app/settings#ai
- generic:
- generic:
- generic:
- generic:
- heading [level=3]
- generic: Unknown size
- button:
- img
- generic:
- generic: Unknown file type
- generic:
- button "Download":
- img
- text: Download
- button "Open":
- img
- text: Open
- generic:
- generic:
- generic:
- heading "Import Documents" [level=3]
- button:
- img
- generic:
- generic:
- img
- heading "Drop files here" [level=4]
- paragraph: or click to browse
- button "Browse Files"
- generic:
- button "Cancel"
- button "Upload 0 Files" [disabled]
+134
View File
@@ -0,0 +1,134 @@
# Changelog
## [1.3.0] - Production Ready Release - 2026-04-06
### Added
- **Production Deployment Guide**: Comprehensive documentation for deploying to production
- **Error Handler Middleware**: Centralized error handling with panic recovery
- **Graceful Shutdown**: Proper cleanup of resources on server shutdown
- **Production Configuration**: Optimized settings for production environments
- **Health Check Endpoints**: `/health`, `/ready`, and `/live` for monitoring
- **Database Connection Pooling**: Configured for optimal performance
- **Rate Limiting**: Protection against abuse and DDoS
- **Audit Logging**: Complete tracking of all user actions
- **Security Headers**: HSTS, CSP, X-Frame-Options, etc.
- **Docker Production Compose**: Optimized docker-compose.prod.yml with resource limits
- **Automated Testing Script**: Pre-deployment validation script
- **Backup Scripts**: Automated database and file backups
- **Monitoring Setup**: Prometheus and Grafana integration ready
### Fixed
- **Debug Logging**: Removed all `fmt.Printf` debug statements from production code
- **Graceful Exit**: Changed `os.Exit(0)` to proper graceful shutdown in update handler
- **Error Handling**: Improved error responses across all handlers
- **Search Handler**: Removed verbose debug logging from Brave Search API calls
- **Semantic Search**: Replaced fmt.Printf with proper log.Printf calls
- **Web Scraping**: Added proper logging instead of fmt.Printf
- **Border Consistency**: Fixed dark mode border colors (#262626) across all components
- **Scrollbar Styling**: Consistent scrollbar appearance in light and dark modes
- **Input Validation**: Enhanced security with better input sanitization
- **CORS Configuration**: Proper CORS setup for production environments
### Improved
- **Database Migrations**: Auto-migration with fallback to legacy SQL migrations
- **Cache Strategy**: DragonflyDB integration with intelligent caching
- **Session Management**: Redis-backed sessions with automatic cleanup
- **Performance**: Optimized database queries and connection pooling
- **Security**: Enhanced JWT validation and encryption
- **Logging**: Structured logging with proper log levels
- **Documentation**: Comprehensive deployment and maintenance guides
- **Frontend Styling**: Consistent Papra design system implementation
- **Dark Mode**: Perfect #262626 border consistency
- **Light Mode**: Enhanced shadows and better contrast
- **Responsive Design**: Improved mobile and tablet layouts
### Security
- **Input Validation**: Comprehensive validation middleware
- **SQL Injection Protection**: Parameterized queries throughout
- **XSS Protection**: Proper output encoding
- **CSRF Protection**: Token-based CSRF prevention
- **Rate Limiting**: Per-endpoint rate limiting
- **Secure Cookies**: HTTPOnly and Secure flags
- **Password Hashing**: Bcrypt with proper cost factor
- **2FA Support**: TOTP-based two-factor authentication
- **API Key Management**: Secure API key generation and validation
- **Audit Trail**: Complete audit logging of security events
### Performance
- **Database Indexing**: Optimized indexes on frequently queried fields
- **Query Optimization**: Reduced N+1 queries
- **Caching Layer**: DragonflyDB for session and data caching
- **Connection Pooling**: Configured for high concurrency
- **Gzip Compression**: Enabled for API responses
- **Static Asset Caching**: Browser caching headers
- **Lazy Loading**: Frontend components load on demand
- **Code Splitting**: Optimized bundle sizes
### DevOps
- **Docker Multi-Stage Builds**: Smaller image sizes
- **Health Checks**: Kubernetes-ready health endpoints
- **Log Rotation**: Automatic log management
- **Resource Limits**: CPU and memory limits in Docker
- **Horizontal Scaling**: Load balancer ready
- **Zero-Downtime Deploys**: Rolling update support
- **Backup Automation**: Scheduled backups with retention
- **Monitoring**: Metrics and alerting ready
### Breaking Changes
- None - fully backward compatible
### Deprecated
- Legacy UUID-based schema (auto-migrates to new schema)
- In-memory sessions (replaced with Redis-backed sessions)
### Migration Notes
- Run `go mod tidy` in backend directory
- Update `.env` file with production values
- Generate new JWT_SECRET and ENCRYPTION_KEY
- Review and update CORS settings
- Configure SSL certificates for HTTPS
- Set up database backups
- Configure monitoring and alerting
### Known Issues
- Computer vision OCR is placeholder implementation (requires Tesseract integration)
- GeoIP detection returns "unknown" (requires GeoIP database)
- Email sending requires SMTP configuration
- Screenshot capture requires Chrome/Chromium installation
### Upgrade Instructions
1. Backup your database: `./backup-trackeep.sh`
2. Pull latest changes: `git pull origin main`
3. Update dependencies: `cd backend && go mod tidy && cd ../frontend && npm install`
4. Rebuild containers: `docker-compose -f docker-compose.prod.yml build`
5. Run migrations: `docker-compose -f docker-compose.prod.yml up -d`
6. Verify health: `curl http://localhost:8080/health`
### Contributors
- Enhanced by AI Assistant (Kiro)
- Original project by Dvorinka
### Support
- GitHub Issues: https://github.com/Dvorinka/Trackeep/issues
- Documentation: See PRODUCTION_DEPLOYMENT.md
---
## [1.2.5] - Previous Release
### Features
- Full-stack learning and productivity platform
- User authentication with JWT
- Bookmark management with metadata
- Task tracking with priorities
- File upload and sharing
- Notes with encryption
- Chat with AI integration
- YouTube video bookmarks
- GitHub integration
- Time tracking
- Calendar events
- Analytics dashboard
- Learning paths
- And much more...
-89
View File
@@ -1,89 +0,0 @@
# Trackeep Deployment Guide
## Flexible Deployment Options
Trackeep is designed to work in various deployment scenarios:
### 1. Local Development (localhost)
```bash
# Start with default settings
docker compose up -d
# Frontend will be available via nginx on port 80
# Backend API on port 8080
# Frontend automatically detects API URL: http://localhost:8080/api/v1
```
### 2. Home Network Deployment
```bash
# Set your HOST environment variable
export HOST=192.168.1.100:8080
# Or modify .env
echo "HOST=192.168.1.100:8080" >> .env
docker compose up -d
# Access from any device on your network
# Frontend: http://192.168.1.100
# API: http://192.168.1.100:8080/api/v1
```
### 3. Domain with Cloudflare/Reverse Proxy
```bash
# Set HOST to your domain
export HOST=yourdomain.com
# Configure CORS for your domain
export CORS_ALLOWED_ORIGINS=https://yourdomain.com
docker compose up -d
# Configure Cloudflare to proxy:
# - yourdomain.com → backend:8080
# - app.yourdomain.com → frontend:80
```
### 4. Production HTTPS
```bash
# Set production mode
export GIN_MODE=release
export HOST=yourdomain.com
export CORS_ALLOWED_ORIGINS=https://yourdomain.com
# Use SSL certificates (via Traefik, Nginx, etc.)
docker compose up -d
```
## Environment Variables
### Core Configuration
- `PORT=8080` - Backend port only
- `GIN_MODE=debug|release` - Application mode
- `HOST=` - Auto-detection fallback (optional)
- `CORS_ALLOWED_ORIGINS=*` - Flexible CORS (restrict in production)
### Removed Variables
-`FRONTEND_PORT` - No longer needed
-`OAUTH_PORT` - Moved to oauth-service/.env
-`VITE_API_URL` - Auto-detected via /api/v1/config
### OAuth Service (Separate)
See `oauth-service/.env.example` for OAuth-specific configuration.
## API Detection
The frontend automatically detects the API URL by:
1. Calling `/api/v1/config` endpoint
2. Using the current request's scheme and host
3. Falling back to `HOST` environment variable
4. Final fallback to `localhost:8080`
## Port Management
- **Backend**: Fixed port 8080 (required for API)
- **Frontend**: No port mapping (uses nginx:80 internally)
- **OAuth**: Separate service on port 9090
- **Database**: Port 5432 (internal to Docker network)
This flexibility allows Trackeep to adapt to any deployment scenario while maintaining a consistent configuration approach.
+55
View File
@@ -0,0 +1,55 @@
# Multi-stage build for unified Trackeep image
# Builds both frontend and backend in one package
# Stage 1: Build Frontend
FROM node:22-alpine AS frontend-builder
WORKDIR /app/frontend
COPY frontend/package*.json ./
RUN npm install
COPY frontend/ ./
RUN npm run build
# Stage 2: Build Backend
FROM golang:1.25-alpine AS backend-builder
WORKDIR /app/backend
COPY backend/go.mod backend/go.sum ./
RUN go mod download
COPY backend/ ./
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
# Stage 3: Final unified image
FROM alpine:latest
# Install dependencies
RUN apk --no-cache add ca-certificates tzdata nginx
# Copy backend binary and migrations
COPY --from=backend-builder /app/backend/main /app/main
COPY --from=backend-builder /app/backend/migrations /app/migrations
# Copy frontend build
COPY --from=frontend-builder /app/frontend/dist /usr/share/nginx/html
# Copy branding assets
COPY trackeep.svg /usr/share/nginx/html/
COPY trackeepfavi.png /usr/share/nginx/html/
COPY trackeepfavi_bg.png /usr/share/nginx/html/
# Copy nginx configuration
COPY frontend/nginx.conf /etc/nginx/nginx.conf
# Create directories
RUN mkdir -p /app/uploads /data /var/log/nginx
# Expose single port
EXPOSE 8080
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
# Start script to run both backend and nginx
COPY docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
ENTRYPOINT ["/docker-entrypoint.sh"]
-33
View File
@@ -1,33 +0,0 @@
/* global chrome */
// Create context menu when extension is installed
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
id: 'save-to-trackeep',
title: 'Save to Trackeep',
contexts: ['page', 'link', 'selection', 'image', 'video']
});
});
// Handle context menu click
chrome.contextMenus.onClicked.addListener(async (info, tab) => {
if (info.menuItemId !== 'save-to-trackeep') return;
// Open popup with pre-filled data based on context
const url = info.linkUrl || info.srcUrl || tab?.url || '';
const title = tab?.title || '';
const selection = info.selectionText || '';
// Store temporary data for popup to read
chrome.storage.local.set({
contextMenuData: {
url,
title,
selection,
timestamp: Date.now()
}
}, () => {
// Open the popup (or focus it if already open)
chrome.action.openPopup();
});
});
-29
View File
@@ -1,29 +0,0 @@
{
"manifest_version": 3,
"name": "Trackeep Saver",
"version": "0.1.0",
"description": "Save the current page or a file to your Trackeep account as a bookmark or upload.",
"action": {
"default_popup": "popup.html",
"default_title": "Save to Trackeep"
},
"options_page": "options.html",
"background": {
"service_worker": "background.js"
},
"permissions": [
"storage",
"tabs",
"activeTab",
"contextMenus"
],
"host_permissions": [
"<all_urls>"
],
"icons": {
"16": "icons/icon16.png",
"32": "icons/icon32.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
}
-531
View File
@@ -1,531 +0,0 @@
<!DOCTYPE html>
<html lang="en" data-kb-theme="dark">
<head>
<meta charset="UTF-8" />
<title>Trackeep Saver Options</title>
<style>
/* Modern Inter Font */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
/* Modern CSS Variables - Proton Pass Inspired */
:root {
--bg-primary: #0f0f0f;
--bg-secondary: #1a1a1a;
--bg-tertiary: #262626;
--bg-hover: #2a2a2a;
--bg-active: #333333;
--border-primary: #2a2a2a;
--border-secondary: #333333;
--text-primary: #ffffff;
--text-secondary: #a3a3a3;
--text-tertiary: #737373;
--accent-primary: #3b82f6;
--accent-hover: #2563eb;
--success: #10b981;
--warning: #f59e0b;
--error: #ef4444;
--gradient-primary: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
--gradient-secondary: linear-gradient(135deg, #1a1a1a 0%, #262626 100%);
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.5);
--radius-sm: 6px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-xl: 16px;
}
* {
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
margin: 0;
padding: 0;
min-height: 100vh;
background: var(--bg-primary);
color: var(--text-primary);
line-height: 1.6;
font-size: 14px;
color-scheme: dark;
}
/* Header */
.header {
background: var(--gradient-secondary);
padding: 32px 20px 20px;
border-bottom: 1px solid var(--border-primary);
position: relative;
overflow: hidden;
}
.header::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: var(--gradient-primary);
}
.header-content {
max-width: 640px;
margin: 0 auto;
display: flex;
align-items: center;
gap: 16px;
}
.logo-container {
display: flex;
align-items: center;
gap: 16px;
}
.logo {
width: 48px;
height: 48px;
border-radius: var(--radius-lg);
background: var(--gradient-primary);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: 700;
font-size: 20px;
box-shadow: var(--shadow-lg);
position: relative;
overflow: hidden;
}
.logo::after {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: linear-gradient(45deg, transparent, rgba(255,255,255,0.1), transparent);
transform: rotate(45deg);
animation: shimmer 3s infinite;
}
@keyframes shimmer {
0% { transform: translateX(-100%) translateY(-100%) rotate(45deg); }
100% { transform: translateX(100%) translateY(100%) rotate(45deg); }
}
.title-section {
flex: 1;
}
.title {
font-size: 28px;
font-weight: 700;
color: var(--text-primary);
margin: 0 0 4px 0;
}
.subtitle {
font-size: 14px;
color: var(--text-secondary);
margin: 0;
}
/* Main Content */
.container {
max-width: 640px;
margin: 0 auto;
padding: 32px 20px;
}
/* Sections */
.section {
background: var(--bg-secondary);
border-radius: var(--radius-lg);
padding: 24px;
border: 1px solid var(--border-primary);
margin-bottom: 24px;
transition: all 0.2s ease;
}
.section:hover {
border-color: var(--border-secondary);
box-shadow: var(--shadow-md);
}
.section-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 20px;
}
.section-icon {
width: 32px;
height: 32px;
border-radius: var(--radius-md);
background: var(--gradient-primary);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 16px;
}
.section-title {
font-size: 18px;
font-weight: 600;
color: var(--text-primary);
margin: 0;
}
/* Form Elements */
.form-group {
margin-bottom: 20px;
}
.form-group:last-child {
margin-bottom: 0;
}
label {
display: block;
font-size: 13px;
font-weight: 500;
margin-bottom: 8px;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.5px;
}
input[type="text"],
input[type="url"],
input[type="password"] {
width: 100%;
padding: 14px 16px;
border-radius: var(--radius-md);
border: 1px solid var(--border-primary);
background: var(--bg-tertiary);
color: var(--text-primary);
font-size: 14px;
font-family: 'Inter', sans-serif;
font-weight: 400;
transition: all 0.2s ease;
outline: none;
}
input[type="text"]:focus,
input[type="url"]:focus,
input[type="password"]:focus {
border-color: var(--accent-primary);
background: var(--bg-hover);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
/* Instructions */
.instructions {
background: var(--bg-tertiary);
border-radius: var(--radius-md);
padding: 16px;
border: 1px solid var(--border-primary);
margin-top: 16px;
}
.instructions-title {
font-size: 13px;
font-weight: 600;
color: var(--text-primary);
margin: 0 0 8px 0;
display: flex;
align-items: center;
gap: 6px;
}
.instructions-list {
font-size: 13px;
color: var(--text-secondary);
margin: 0;
padding-left: 16px;
line-height: 1.6;
}
.instructions-list li {
margin-bottom: 4px;
}
.instructions-list li:last-child {
margin-bottom: 0;
}
/* Buttons */
.btn {
padding: 14px 24px;
border-radius: var(--radius-md);
border: none;
font-size: 14px;
font-weight: 500;
font-family: 'Inter', sans-serif;
cursor: pointer;
transition: all 0.2s ease;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
outline: none;
position: relative;
overflow: hidden;
}
.btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.1), transparent);
transition: left 0.5s;
}
.btn:hover::before {
left: 100%;
}
.btn-primary {
background: var(--gradient-primary);
color: white;
box-shadow: var(--shadow-sm);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-md);
}
.btn-primary:active {
transform: translateY(0);
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none !important;
}
/* Status Messages */
.status-message {
padding: 16px 20px;
border-radius: var(--radius-md);
font-size: 13px;
font-weight: 500;
margin-top: 20px;
display: flex;
align-items: center;
gap: 10px;
animation: slideUp 0.3s ease;
}
@keyframes slideUp {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.status-message.success {
background: rgba(16, 185, 129, 0.1);
color: var(--success);
border: 1px solid rgba(16, 185, 129, 0.2);
}
.status-message.error {
background: rgba(239, 68, 68, 0.1);
color: var(--error);
border: 1px solid rgba(239, 68, 68, 0.2);
}
.status-message.info {
background: rgba(59, 130, 246, 0.1);
color: var(--accent-primary);
border: 1px solid rgba(59, 130, 246, 0.2);
}
/* Code styling */
code {
background: var(--bg-tertiary);
padding: 3px 8px;
border-radius: var(--radius-sm);
font-size: 12px;
color: var(--text-primary);
border: 1px solid var(--border-primary);
font-family: 'Fira Code', 'Monaco', 'Consolas', monospace;
}
/* Icon System */
.icon {
width: 16px;
height: 16px;
display: inline-block;
vertical-align: middle;
transition: all 0.2s ease;
}
.icon-sm {
width: 12px;
height: 12px;
}
.icon-lg {
width: 20px;
height: 20px;
}
.icon-xl {
width: 24px;
height: 24px;
}
/* Icon animations */
.icon-spin {
animation: spin 1s linear infinite;
}
.icon-pulse {
animation: pulse 2s ease-in-out infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.8; transform: scale(1.05); }
}
/* Enhanced button icons */
.btn .icon {
transition: transform 0.2s ease;
}
.btn:hover .icon {
transform: scale(1.1);
}
.btn:active .icon {
transform: scale(0.95);
}
/* Section icon enhancements */
.section-icon {
transition: all 0.3s ease;
}
.section:hover .section-icon {
transform: scale(1.05) rotate(5deg);
box-shadow: var(--shadow-md);
}
/* Responsive */
@media (max-width: 640px) {
.container {
padding: 20px 16px;
}
.section {
padding: 20px;
}
.header {
padding: 24px 16px 16px;
}
.title {
font-size: 24px;
}
}
</style>
</head>
<body>
<!-- Header -->
<header class="header">
<div class="header-content">
<div class="logo-container">
<div class="logo">T</div>
<div class="title-section">
<h1 class="title">Trackeep Saver</h1>
<p class="subtitle">Configure your extension settings</p>
</div>
</div>
</div>
</header>
<!-- Main Content -->
<main class="container">
<div class="section">
<div class="section-header">
<div class="section-icon">
<svg class="icon-xl" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="3"/>
<path d="M12 1v6m0 6v6m4.22-13.22l4.24 4.24M1.54 1.54l4.24 4.24M1 12h6m6 0h6"/>
</svg>
</div>
<h2 class="section-title">API Configuration</h2>
</div>
<div class="form-group">
<label for="apiBaseUrl">Trackeep API Base URL</label>
<input
id="apiBaseUrl"
type="url"
placeholder="https://your-domain.example.com/api/v1 or http://localhost:8080/api/v1"
/>
</div>
<div class="form-group">
<label for="authToken">Authentication Token (JWT)</label>
<input
id="authToken"
type="password"
placeholder="Paste your Trackeep authentication token here"
/>
</div>
<div class="instructions">
<div class="instructions-title">
<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
<polyline points="14,2 14,8 20,8"/>
<line x1="16" y1="13" x2="8" y2="13"/>
<line x1="16" y1="17" x2="8" y2="17"/>
<polyline points="10,9 9,9 8,9"/>
</svg>
<span>How to get your authentication token:</span>
</div>
<ol class="instructions-list">
<li>Log into your Trackeep account in your browser</li>
<li>Open Developer Tools (F12) → Application → Local Storage</li>
<li>Find key <code>trackeep_token</code> and copy its value</li>
<li>Paste token in field above</li>
<li><strong>Never share this token publicly</strong> - it provides full access to your account</li>
</ol>
</div>
<button class="btn btn-primary" id="saveBtn" style="margin-top: 24px;">
<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/>
<polyline points="17,21 17,13 7,13 7,21"/>
<polyline points="7,3 7,8 15,8"/>
</svg>
<span>Save Settings</span>
</button>
<div id="statusMessage" class="status-message" style="display: none;"></div>
</div>
</main>
<script src="options.js"></script>
</body>
</html>
-136
View File
@@ -1,136 +0,0 @@
/* global chrome */
const apiBaseUrlInput = document.getElementById('apiBaseUrl');
const authTokenInput = document.getElementById('authToken');
const saveBtn = document.getElementById('saveBtn');
const statusMessageEl = document.getElementById('statusMessage');
function showMessage(message, type = 'info', duration = 5000) {
statusMessageEl.textContent = message;
statusMessageEl.className = `status-message ${type}`;
statusMessageEl.style.display = 'flex';
if (duration > 0) {
setTimeout(() => {
statusMessageEl.style.display = 'none';
}, duration);
}
}
function hideMessage() {
statusMessageEl.style.display = 'none';
}
function setButtonLoading(button, loading = true) {
if (loading) {
button.disabled = true;
const originalContent = button.innerHTML;
button.dataset.originalContent = originalContent;
button.innerHTML = `
<svg class="icon icon-spin" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 12a9 9 0 1 1-6.219-8.56"/>
</svg>
<span>Saving...</span>
`;
} else {
button.disabled = false;
if (button.dataset.originalContent) {
button.innerHTML = button.dataset.originalContent;
delete button.dataset.originalContent;
}
}
}
function detectAndPrefillApiBaseUrl(callback) {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
const tab = tabs && tabs[0];
if (!tab || !tab.url) {
if (callback) callback();
return;
}
try {
const url = new URL(tab.url);
const isTrackeepDomain = url.hostname.includes('trackeep') || url.hostname === 'localhost';
if (isTrackeepDomain && (url.protocol === 'https:' || url.protocol === 'http:')) {
const candidate = `${url.origin}/api/v1`;
chrome.storage.sync.get(['trackeepApiBaseUrl'], (items) => {
if (!items.trackeepApiBaseUrl) {
apiBaseUrlInput.value = candidate;
}
if (callback) callback();
});
} else {
// Fallback to localhost if nothing set
chrome.storage.sync.get(['trackeepApiBaseUrl'], (items) => {
if (!items.trackeepApiBaseUrl) {
apiBaseUrlInput.value = 'http://localhost:8080/api/v1';
}
if (callback) callback();
});
}
} catch (e) {
if (callback) callback();
}
});
}
function loadSettings() {
chrome.storage.sync.get(['trackeepApiBaseUrl', 'trackeepAuthToken'], (items) => {
if (items.trackeepApiBaseUrl) {
apiBaseUrlInput.value = items.trackeepApiBaseUrl;
}
if (items.trackeepAuthToken) {
authTokenInput.value = items.trackeepAuthToken;
}
});
}
function saveSettings() {
const apiBaseUrl = apiBaseUrlInput.value.trim();
const authToken = authTokenInput.value.trim();
if (!apiBaseUrl) {
showMessage('API base URL is required.', 'error');
return;
}
if (!authToken) {
showMessage('Authentication token is required.', 'error');
return;
}
setButtonLoading(saveBtn, true);
hideMessage();
chrome.storage.sync.set(
{
trackeepApiBaseUrl: apiBaseUrl,
trackeepAuthToken: authToken
},
() => {
setButtonLoading(saveBtn, false);
if (chrome.runtime.lastError) {
showMessage(`Failed to save: ${chrome.runtime.lastError.message}`, 'error');
} else {
showMessage(`
<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="20,6 9,17 4,12"/>
</svg>
Settings saved successfully! You can now use the extension to save bookmarks and files.
`, 'success');
}
}
);
}
// Initialize everything when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
detectAndPrefillApiBaseUrl(() => {
loadSettings();
saveBtn.addEventListener('click', (e) => {
e.preventDefault();
saveSettings();
});
});
});
-880
View File
@@ -1,880 +0,0 @@
<!DOCTYPE html>
<html lang="en" data-kb-theme="dark">
<head>
<meta charset="UTF-8" />
<title>Trackeep Saver</title>
<style>
/* Modern Inter Font */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
/* Modern CSS Variables - Proton Pass Inspired */
:root {
--bg-primary: #0f0f0f;
--bg-secondary: #1a1a1a;
--bg-tertiary: #262626;
--bg-hover: #2a2a2a;
--bg-active: #333333;
--border-primary: #2a2a2a;
--border-secondary: #333333;
--text-primary: #ffffff;
--text-secondary: #a3a3a3;
--text-tertiary: #737373;
--accent-primary: #3b82f6;
--accent-hover: #2563eb;
--success: #10b981;
--warning: #f59e0b;
--error: #ef4444;
--gradient-primary: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
--gradient-secondary: linear-gradient(135deg, #1a1a1a 0%, #262626 100%);
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.5);
--radius-sm: 6px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-xl: 16px;
}
* {
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
margin: 0;
padding: 0;
min-width: 400px;
max-width: 440px;
background: var(--bg-primary);
color: var(--text-primary);
line-height: 1.5;
font-size: 14px;
color-scheme: dark;
overflow-x: hidden;
}
/* Header */
.header {
background: var(--gradient-secondary);
padding: 20px 20px 16px;
border-bottom: 1px solid var(--border-primary);
position: relative;
overflow: hidden;
}
.header::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: var(--gradient-primary);
}
.header-content {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
}
.logo-container {
display: flex;
align-items: center;
gap: 12px;
}
/* Enhanced logo animation */
.logo {
width: 32px;
height: 32px;
border-radius: var(--radius-md);
background: var(--gradient-primary);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: 700;
font-size: 16px;
box-shadow: var(--shadow-md);
position: relative;
overflow: hidden;
transition: all 0.3s ease;
}
.logo:hover {
transform: scale(1.05) rotate(5deg);
box-shadow: var(--shadow-lg);
}
.logo::after {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: linear-gradient(45deg, transparent, rgba(255,255,255,0.1), transparent);
transform: rotate(45deg);
animation: shimmer 3s infinite;
}
@keyframes shimmer {
0% { transform: translateX(-100%) translateY(-100%) rotate(45deg); }
100% { transform: translateX(100%) translateY(100%) rotate(45deg); }
}
/* Enhanced options button */
.options-btn {
width: 32px;
height: 32px;
border-radius: var(--radius-md);
background: var(--bg-tertiary);
border: 1px solid var(--border-primary);
color: var(--text-secondary);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
font-size: 14px;
position: relative;
overflow: hidden;
}
.options-btn::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
background: var(--accent-primary);
border-radius: 50%;
transform: translate(-50%, -50%);
transition: all 0.3s ease;
opacity: 0.1;
}
.options-btn:hover {
background: var(--bg-hover);
color: var(--text-primary);
border-color: var(--accent-primary);
transform: translateY(-1px);
box-shadow: var(--shadow-md);
}
.options-btn:hover::before {
width: 100%;
height: 100%;
}
.title {
font-size: 18px;
font-weight: 600;
color: var(--text-primary);
margin: 0;
}
/* Status Bar */
.status-bar {
padding: 8px 20px;
background: var(--bg-secondary);
border-bottom: 1px solid var(--border-primary);
min-height: 36px;
display: flex;
align-items: center;
gap: 8px;
}
.status-indicator {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--text-tertiary);
animation: pulse 2s infinite;
}
.status-indicator.connected {
background: var(--success);
}
.status-indicator.error {
background: var(--error);
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.status-text {
font-size: 12px;
color: var(--text-secondary);
flex: 1;
}
/* Main Content */
.content {
padding: 20px;
}
/* Tabs */
.tabs {
display: flex;
gap: 4px;
margin-bottom: 20px;
background: var(--bg-secondary);
padding: 4px;
border-radius: var(--radius-lg);
border: 1px solid var(--border-primary);
}
.tab {
flex: 1;
padding: 10px 16px;
border-radius: var(--radius-md);
background: transparent;
border: none;
color: var(--text-secondary);
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
.tab:hover {
background: var(--bg-hover);
color: var(--text-primary);
}
.tab.active {
background: var(--bg-primary);
color: var(--text-primary);
box-shadow: var(--shadow-sm);
border: 1px solid var(--border-secondary);
}
.tab-icon {
font-size: 14px;
}
/* Tab Content */
.tab-content {
display: none;
animation: fadeIn 0.3s ease;
}
.tab-content.active {
display: block;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
/* Form Sections */
.form-section {
background: var(--bg-secondary);
border-radius: var(--radius-lg);
padding: 20px;
border: 1px solid var(--border-primary);
margin-bottom: 16px;
transition: all 0.2s ease;
}
.form-section:hover {
border-color: var(--border-secondary);
box-shadow: var(--shadow-sm);
}
.section-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 16px;
}
.section-icon {
width: 24px;
height: 24px;
border-radius: var(--radius-sm);
background: var(--gradient-primary);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 12px;
}
.section-title {
font-size: 14px;
font-weight: 600;
color: var(--text-primary);
margin: 0;
}
/* Form Elements */
.form-group {
margin-bottom: 16px;
position: relative;
}
.form-group:last-child {
margin-bottom: 0;
}
label {
display: block;
font-size: 12px;
font-weight: 500;
margin-bottom: 6px;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.5px;
transition: color 0.2s ease;
}
.form-group:focus-within label {
color: var(--accent-primary);
}
input[type="text"],
input[type="url"],
input[type="file"],
textarea {
width: 100%;
padding: 12px 14px;
border-radius: var(--radius-md);
border: 1px solid var(--border-primary);
background: var(--bg-tertiary);
color: var(--text-primary);
font-size: 13px;
font-family: 'Inter', sans-serif;
font-weight: 400;
transition: all 0.2s ease;
outline: none;
position: relative;
}
input[type="text"]:hover,
input[type="url"]:hover,
textarea:hover {
border-color: var(--border-secondary);
background: var(--bg-hover);
}
input[type="text"]:focus,
input[type="url"]:focus,
textarea:focus {
border-color: var(--accent-primary);
background: var(--bg-hover);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
transform: translateY(-1px);
}
input[type="file"] {
padding: 10px;
cursor: pointer;
transition: all 0.2s ease;
}
input[type="file"]:hover {
border-color: var(--accent-primary);
background: var(--bg-hover);
}
textarea {
resize: vertical;
min-height: 80px;
font-family: inherit;
}
/* Input field icons */
.input-icon {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
color: var(--text-tertiary);
font-size: 14px;
pointer-events: none;
transition: color 0.2s ease;
}
.form-group:focus-within .input-icon {
color: var(--accent-primary);
}
/* Checkbox */
.checkbox-group {
display: flex;
align-items: center;
gap: 8px;
padding: 12px;
background: var(--bg-tertiary);
border-radius: var(--radius-md);
border: 1px solid var(--border-primary);
cursor: pointer;
transition: all 0.2s ease;
}
.checkbox-group:hover {
background: var(--bg-hover);
border-color: var(--border-secondary);
}
.checkbox-group input[type="checkbox"] {
width: 16px;
height: 16px;
margin: 0;
cursor: pointer;
accent-color: var(--accent-primary);
}
.checkbox-label {
font-size: 13px;
color: var(--text-primary);
margin: 0;
font-weight: 400;
user-select: none;
}
/* Buttons */
.btn {
padding: 12px 20px;
border-radius: var(--radius-md);
border: none;
font-size: 13px;
font-weight: 500;
font-family: 'Inter', sans-serif;
cursor: pointer;
transition: all 0.2s ease;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
outline: none;
position: relative;
overflow: hidden;
}
.btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.1), transparent);
transition: left 0.5s;
}
.btn:hover::before {
left: 100%;
}
.btn-primary {
background: var(--gradient-primary);
color: white;
box-shadow: var(--shadow-sm);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-md);
}
.btn-primary:active {
transform: translateY(0);
box-shadow: var(--shadow-sm);
}
.btn-secondary {
background: var(--bg-tertiary);
color: var(--text-primary);
border: 1px solid var(--border-primary);
}
.btn-secondary:hover {
background: var(--bg-hover);
border-color: var(--border-secondary);
transform: translateY(-1px);
box-shadow: var(--shadow-sm);
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none !important;
box-shadow: none !important;
}
.btn-block {
width: 100%;
}
.btn-group {
display: flex;
gap: 12px;
align-items: center;
justify-content: space-between;
}
/* Enhanced status bar animations */
.status-bar {
padding: 8px 20px;
background: var(--bg-secondary);
border-bottom: 1px solid var(--border-primary);
min-height: 36px;
display: flex;
align-items: center;
gap: 8px;
transition: all 0.3s ease;
}
.status-bar:hover {
background: var(--bg-hover);
}
/* Enhanced tab animations */
.tab {
flex: 1;
padding: 10px 16px;
border-radius: var(--radius-md);
background: transparent;
border: none;
color: var(--text-secondary);
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
position: relative;
}
.tab::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
width: 0;
height: 2px;
background: var(--accent-primary);
transition: all 0.3s ease;
transform: translateX(-50%);
}
.tab:hover {
background: var(--bg-hover);
color: var(--text-primary);
transform: translateY(-1px);
}
.tab:hover::after {
width: 30%;
}
.tab.active {
background: var(--bg-primary);
color: var(--text-primary);
box-shadow: var(--shadow-sm);
border: 1px solid var(--border-secondary);
}
.tab.active::after {
width: 60%;
}
/* Status Messages */
.status-message {
padding: 12px 16px;
border-radius: var(--radius-md);
font-size: 12px;
font-weight: 500;
margin-top: 16px;
display: flex;
align-items: center;
gap: 8px;
animation: slideUp 0.3s ease;
}
@keyframes slideUp {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.status-message.success {
background: rgba(16, 185, 129, 0.1);
color: var(--success);
border: 1px solid rgba(16, 185, 129, 0.2);
}
.status-message.error {
background: rgba(239, 68, 68, 0.1);
color: var(--error);
border: 1px solid rgba(239, 68, 68, 0.2);
}
.status-message.info {
background: rgba(59, 130, 246, 0.1);
color: var(--accent-primary);
border: 1px solid rgba(59, 130, 246, 0.2);
}
/* Icon System */
.icon {
width: 16px;
height: 16px;
display: inline-block;
vertical-align: middle;
transition: all 0.2s ease;
}
.icon-sm {
width: 12px;
height: 12px;
}
.icon-lg {
width: 20px;
height: 20px;
}
.icon-xl {
width: 24px;
height: 24px;
}
/* Icon animations */
.icon-spin {
animation: spin 1s linear infinite;
}
.icon-pulse {
animation: pulse 2s ease-in-out infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.8; transform: scale(1.05); }
}
/* Enhanced button icons */
.btn .icon {
transition: transform 0.2s ease;
}
.btn:hover .icon {
transform: scale(1.1);
}
.btn:active .icon {
transform: scale(0.95);
}
/* Tab icon enhancements */
.tab .icon {
transition: all 0.3s ease;
}
.tab:hover .icon {
transform: translateY(-1px) scale(1.1);
}
.tab.active .icon {
color: var(--accent-primary);
transform: scale(1.1);
}
/* Section icon enhancements */
.section-icon {
transition: all 0.3s ease;
}
.form-section:hover .section-icon {
transform: scale(1.05);
box-shadow: var(--shadow-md);
}
/* Status indicator enhancements */
.status-indicator {
transition: all 0.3s ease;
}
.status-indicator.connected {
box-shadow: 0 0 8px rgba(16, 185, 129, 0.5);
}
.status-indicator.error {
box-shadow: 0 0 8px rgba(239, 68, 68, 0.5);
}
/* Responsive */
@media (max-width: 420px) {
body {
min-width: 360px;
}
.content {
padding: 16px;
}
.form-section {
padding: 16px;
}
}
</style>
</head>
<body>
<!-- Header -->
<header class="header">
<div class="header-content">
<div class="logo-container">
<div class="logo">T</div>
<h1 class="title">Trackeep</h1>
</div>
<button class="options-btn" id="openOptions" title="Settings">
<svg class="icon icon-lg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="3"/>
<path d="M12 1v6m0 6v6m4.22-13.22l4.24 4.24M1.54 1.54l4.24 4.24M1 12h6m6 0h6"/>
</svg>
</button>
</div>
</header>
<!-- Status Bar -->
<div class="status-bar">
<div class="status-indicator" id="statusIndicator"></div>
<div class="status-text" id="statusText">Checking configuration...</div>
</div>
<!-- Main Content -->
<main class="content">
<!-- Tabs -->
<div class="tabs">
<button class="tab active" data-tab="bookmark">
<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/>
</svg>
<span>Bookmark</span>
</button>
<button class="tab" data-tab="file">
<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
<polyline points="14,2 14,8 20,8"/>
</svg>
<span>File</span>
</button>
</div>
<!-- Bookmark Tab -->
<div class="tab-content active" id="bookmark-tab">
<div class="form-section">
<div class="section-header">
<div class="section-icon">
<svg class="icon-xl" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/>
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/>
</svg>
</div>
<h2 class="section-title">Save Current Page</h2>
</div>
<div class="form-group">
<label for="bookmarkTitle">Title</label>
<input id="bookmarkTitle" type="text" placeholder="Page title will be auto-filled" />
</div>
<div class="form-group">
<label for="bookmarkUrl">URL</label>
<input id="bookmarkUrl" type="url" placeholder="https://example.com" />
</div>
<div class="form-group">
<label for="bookmarkDescription">Description</label>
<textarea id="bookmarkDescription" placeholder="Why is this page important? Add notes..."></textarea>
</div>
<div class="form-group">
<label for="bookmarkTags">Tags</label>
<input id="bookmarkTags" type="text" placeholder="reading, development, tutorial" />
</div>
<div class="form-group">
<div class="checkbox-group">
<input id="bookmarkPublic" type="checkbox" />
<label for="bookmarkPublic" class="checkbox-label">Make this bookmark public</label>
</div>
</div>
<div class="btn-group">
<div></div>
<button class="btn btn-primary" id="saveBookmarkBtn">
<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/>
<polyline points="17,21 17,13 7,13 7,21"/>
<polyline points="7,3 7,8 15,8"/>
</svg>
<span>Save Bookmark</span>
</button>
</div>
</div>
</div>
<!-- File Tab -->
<div class="tab-content" id="file-tab">
<div class="form-section">
<div class="section-header">
<div class="section-icon">
<svg class="icon-xl" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="17,8 12,3 7,8"/>
<line x1="12" y1="3" x2="12" y2="15"/>
</svg>
</div>
<h2 class="section-title">Upload File</h2>
</div>
<div class="form-group">
<label for="fileInput">Choose File</label>
<input id="fileInput" type="file" />
</div>
<div class="form-group">
<label for="fileDescription">Description</label>
<textarea id="fileDescription" placeholder="Describe this file..."></textarea>
</div>
<button class="btn btn-primary btn-block" id="uploadFileBtn">
<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
<polyline points="17,8 12,3 7,8"/>
<line x1="12" y1="3" x2="12" y2="15"/>
</svg>
<span>Upload File</span>
</button>
</div>
</div>
<!-- Status Message -->
<div id="statusMessage" class="status-message" style="display: none;"></div>
</main>
<script src="popup.js"></script>
</body>
</html>
-192
View File
@@ -1,192 +0,0 @@
# Trackeep Mobile App
React Native mobile application for Trackeep - productivity and knowledge management platform.
## Features
### ✅ Core Features Implemented
- **🔐 Authentication**: Login with email/password and GitHub OAuth
- **📱 Offline Support**: Full offline functionality with sync when online
- **📝 Content Management**: Bookmarks, Tasks, Notes, and Time Tracking
- **🔍 Search**: Unified search across all content types
- **⏱️ Time Tracking**: Built-in timer with task association
- **🎨 Modern UI**: Material Design with React Native Paper
- **📊 Dashboard**: Overview with stats and recent activity
### ✅ Mobile-Specific Features
- **Gesture Navigation**: Intuitive mobile navigation patterns
- **Push Notifications**: Task reminders and updates with permission management
- **Camera Integration**: Document scanning capability with permission handling
- **Voice Notes**: Audio recording for quick notes with speech-to-text
- **Background Sync**: Automatic data synchronization
- **Responsive Design**: Optimized for various screen sizes
## Tech Stack
- **React Native** 0.72.6
- **TypeScript** for type safety
- **React Navigation** for navigation
- **React Native Paper** for UI components
- **AsyncStorage** for local data persistence
- **Axios** for API communication
- **Vector Icons** for iconography
## Project Structure
```
mobile-app/
├── src/
│ ├── components/ # Reusable UI components
│ ├── screens/ # Screen components
│ │ ├── auth/ # Authentication screens
│ │ ├── DashboardScreen.tsx
│ │ ├── BookmarksScreen.tsx
│ │ ├── TasksScreen.tsx
│ │ ├── NotesScreen.tsx
│ │ ├── TimeTrackingScreen.tsx
│ │ ├── SearchScreen.tsx
│ │ └── SettingsScreen.tsx
│ ├── services/ # Business logic and API
│ │ ├── AuthContext.tsx
│ │ ├── OfflineContext.tsx
│ │ └── api.ts
│ ├── navigation/ # Navigation configuration
│ ├── utils/ # Utility functions
│ │ ├── storage.ts
│ │ └── offlineSync.ts
│ └── types/ # TypeScript type definitions
├── android/ # Android-specific code
├── ios/ # iOS-specific code
└── package.json
```
## Getting Started
### Prerequisites
- Node.js 16+
- React Native CLI
- Android Studio (for Android development)
- Xcode (for iOS development)
### Installation
1. Clone the repository:
```bash
git clone <repository-url>
cd Trackeep/mobile-app
```
2. Install dependencies:
```bash
npm install
```
3. For iOS, install pods:
```bash
cd ios && pod install && cd ..
```
### Running the App
#### Android
```bash
npm run android
```
#### iOS
```bash
npm run ios
```
#### Start Metro Bundler
```bash
npm start
```
## Configuration
### Environment Variables
Create a `.env` file in the root directory:
```env
API_BASE_URL=http://localhost:8080/api
```
### API Configuration
Update the API base URL in `src/services/api.ts` to match your backend server.
## Features Status
### ✅ Completed
- [x] Project setup and configuration
- [x] Authentication flow (email/password, GitHub)
- [x] Navigation structure
- [x] Core screens (Dashboard, Bookmarks, Tasks, Notes, Time Tracking, Search, Settings)
- [x] Offline data storage and sync
- [x] Modern UI with Material Design
- [x] TypeScript integration
- [x] API service layer
- [x] Push notification implementation with permission management
- [x] Camera integration for document scanning
- [x] Voice recording for notes with speech-to-text
- [x] Enhanced settings screen with mobile features
### 📋 Planned
- [ ] Biometric authentication
- [ ] Dark mode theme
- [ ] Widget support
- [ ] Apple Watch companion app
- [ ] Advanced analytics
## Development
### Code Style
The project uses TypeScript and follows React Native best practices. All components are functional components with hooks.
### State Management
- **Authentication**: React Context (AuthContext)
- **Offline Sync**: React Context (OfflineContext)
- **Local Data**: AsyncStorage with SQLite for complex queries
### API Integration
All API calls are centralized in `src/services/api.ts` with automatic token management and error handling.
## Testing
```bash
npm test
```
## Building
### Android Release Build
```bash
npm run build:android
```
### iOS Release Build
```bash
npm run build:ios
```
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests if applicable
5. Submit a pull request
## License
This project is licensed under the MIT License.
## Support
For support and questions, please open an issue in the repository.
-210
View File
@@ -1,210 +0,0 @@
# Mobile App Sync Testing Guide
## Overview
This guide helps you test the bi-directional synchronization between the Trackeep mobile app and web dashboard.
## Prerequisites
1. **Backend Server**: Ensure your Trackeep backend is running
2. **Web Dashboard**: Access the web dashboard at `http://localhost:3000` (or your configured URL)
3. **Mobile App**: Run the React Native app using:
```bash
npm start
npm run android # or npm run ios
```
## First Launch Setup
1. **Server Configuration**: On first launch, the mobile app will show the server setup screen:
- Enter your backend URL (e.g., `http://localhost:8080`)
- Enter your credentials
- Test connection before completing setup
2. **Authentication**: After setup, you'll be redirected to login with your existing credentials
## Testing Real-Time Sync
### Test 1: Create Content on Mobile, Verify on Web
1. **On Mobile App**:
- Open the Dashboard
- Tap the FAB (+) button
- Create a new task, bookmark, or note
- Verify it appears in the mobile dashboard
2. **On Web Dashboard**:
- Navigate to the corresponding section (Tasks, Bookmarks, or Notes)
- The new item should appear within seconds (if WebSocket is connected)
- If not, refresh the page to see the synced item
### Test 2: Create Content on Web, Verify on Mobile
1. **On Web Dashboard**:
- Create a new task, bookmark, or note
- Save the item
2. **On Mobile App**:
- The item should appear automatically if real-time sync is working
- Pull to refresh on the dashboard to force sync
- Check the specific section to verify the item appears
### Test 3: Offline Mode Testing
1. **Enable Offline Mode**:
- Turn off internet connection on your mobile device
- The app should show "🔴 Offline" status
2. **Create Content Offline**:
- Create several tasks, bookmarks, or notes
- Notice the pending changes counter increases
3. **Restore Connection**:
- Turn internet back on
- App should show "🟢 Connected" and auto-sync
- Verify items appear on web dashboard
### Test 4: Conflict Resolution
1. **Simulate Conflict**:
- Create the same item on both mobile and web while offline
- Bring both online simultaneously
- Verify how conflicts are resolved (last write wins or merge)
## Key Features to Test
### Real-Time Updates
- ✅ WebSocket connection status
- ✅ Instant updates across devices
- ✅ Connection recovery after disconnection
### Offline Support
- ✅ Offline data persistence
- ✅ Pending changes tracking
- ✅ Automatic sync when online
- ✅ Manual sync button
### Data Integrity
- ✅ All data types sync correctly (tasks, bookmarks, notes)
- ✅ Timestamps preserved
- ✅ User associations maintained
- ✅ Tags and metadata sync
## Troubleshooting
### Common Issues
1. **WebSocket Connection Failed**:
- Check if backend WebSocket endpoint is accessible
- Verify firewall settings
- Check browser console for WebSocket errors
2. **Sync Not Working**:
- Verify server URL in mobile app settings
- Check authentication tokens
- Review backend logs for sync errors
3. **Offline Mode Not Detected**:
- Check network permissions on mobile device
- Verify NetInfo plugin is working
- Test with airplane mode
### Debug Tools
1. **Mobile App Debugging**:
```bash
# Enable debug mode
npx react-native log-android
npx react-native log-ios
```
2. **Backend Logs**:
- Monitor sync endpoint logs
- Check WebSocket connection logs
- Review database transaction logs
3. **Browser Console**:
- Monitor WebSocket connections
- Check for real-time update events
- Verify API responses
## Performance Testing
### Test Scenarios
1. **Large Dataset Sync**:
- Create 100+ items on one device
- Measure sync time to other device
- Verify no data loss
2. **Concurrent Updates**:
- Multiple users updating same data
- Test conflict resolution
- Verify data consistency
3. **Network Conditions**:
- Test on slow networks (2G/3G)
- Test with intermittent connectivity
- Verify sync resilience
## Expected Results
### Successful Sync Indicators
1. **Mobile App**:
- Status shows "🟢 Connected"
- Last sync time updates
- No pending changes counter
- Real-time updates received
2. **Web Dashboard**:
- New items appear without refresh
- WebSocket connection established
- No sync errors in console
### Performance Benchmarks
- **Small items** (< 1KB): Should sync within 1-2 seconds
- **Large items** (> 100KB): Should sync within 5-10 seconds
- **Batch sync** (50+ items): Should complete within 30 seconds
## Automated Testing
For comprehensive testing, consider implementing:
1. **Unit Tests**:
- Sync logic validation
- Offline queue management
- Conflict resolution
2. **Integration Tests**:
- End-to-end sync workflows
- WebSocket connection testing
- API integration validation
3. **E2E Tests**:
- Multi-device sync scenarios
- Offline/online transitions
- User interaction flows
## Reporting Issues
When reporting sync issues, include:
1. Device information (OS, version)
2. Network conditions
3. Steps to reproduce
4. Screenshots of error messages
5. Backend logs (if available)
6. Browser console errors
## Success Criteria
The sync implementation is considered successful when:
- ✅ All data types sync bi-directionally
- ✅ Real-time updates work within 5 seconds
- ✅ Offline mode functions correctly
- ✅ No data loss during sync
- ✅ Conflicts are handled gracefully
- ✅ Performance meets benchmarks
- ✅ Error recovery works reliably
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1024 1024">
<!-- Generator: Adobe Illustrator 29.7.1, SVG Export Plug-In . SVG Version: 2.1.1 Build 8) -->
<path fill="#3b82f6" d="M797.56,348.33c30.91,6.66,83.06,31.07,87.21,66.41,3.15,26.85-13.06,79.89-19.48,108.33-18.08,80.05-35.49,169.43-58.24,247.51-37.84,129.87-259.97,143.84-369.81,131-79.98-9.34-191.79-42.13-218.72-127.8l-79.09-341.68c-6.97-50.68,49.68-73.96,89.21-85.61,54.67-16.12,110.4-16.62,167.08-15.62l-45.47,16.39c-44.91,18.53-101.62,26.35-145.23,45.5-15.84,6.96-26.94,19.89-14.58,36.36,18.56,24.72,115.14,56.1,146.77,62.89,82.16,17.65,152.89,2.18,231.43-22.46,54.98-17.25,130.36-44.86,168.52-89.18,25.27-29.35,31.42-69.3,44.38-104.84l-243.09,42.99-2,3.82c-1.45,15.08-2.76,30.11-6.03,44.92-31.75,143.69-186.99,93.71-283.19,53.84l1.47-2.15c82.39-23.86,163.75-50.91,245.03-78.2,5.91-3.48,5.08-25.81,7.22-33.55,3.45-12.47,12.22-19.65,23.97-24.08l282.88-49.24c14.15,3.11,20.4,11.87,18.9,26.37l-29.13,88.06v.02ZM841.24,457.54l-19.61,14.59c-113.51,75.99-355.25,76.96-485.87,53.37-58.02-10.48-91.56-24.33-143.96-48.22-1.22-.56-3.68-1.88-4.26-.11,9.51,23.92,8.86,56.35,22.36,78.1,28.12,45.3,113.96,67.69,163.71,76.52,72.61,12.88,148.98,14.98,222.29,7.73,63.62-6.3,204.67-30.25,226.3-101.29,7.88-25.88,11.16-54.64,19.03-80.69h0ZM806.3,607.51l-30.5,18.26c-131.73,66.26-405.38,65.51-535.38-4.91-6.49-3.51-12.31-8.25-18.62-11.96-1.12-.66-2.56-2.94-3.72-.65,11.55,32.54,8.2,71.49,34.17,96.87,59.84,58.47,212.94,70.07,292.78,66.97,63.99-2.48,191.09-21.71,233.65-73.56,19.02-23.17,17.88-63.15,27.62-91.02h0ZM774.26,744.37c-13.76,6.59-26.7,15.08-40.78,21.08-119.06,50.77-329.26,50.83-447.48-2.37-12.39-5.57-23.46-13.36-35.88-18.71,6.11,30.5,22.34,54.66,47.59,72.51,97.85,69.2,342.24,69.95,436.47-5.6,21.95-17.59,34.7-39.15,40.08-66.92h0Z"/>
<rect fill="#3b82f6" x="468.16" y="171.76" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
<rect fill="#3b82f6" x="593.35" y="118.61" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
<rect fill="#3b82f6" x="361.93" y="250.32" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1024 1024">
<!-- Generator: Adobe Illustrator 29.7.1, SVG Export Plug-In . SVG Version: 2.1.1 Build 8) -->
<path fill="#3b82f6" d="M797.56,348.33c30.91,6.66,83.06,31.07,87.21,66.41,3.15,26.85-13.06,79.89-19.48,108.33-18.08,80.05-35.49,169.43-58.24,247.51-37.84,129.87-259.97,143.84-369.81,131-79.98-9.34-191.79-42.13-218.72-127.8l-79.09-341.68c-6.97-50.68,49.68-73.96,89.21-85.61,54.67-16.12,110.4-16.62,167.08-15.62l-45.47,16.39c-44.91,18.53-101.62,26.35-145.23,45.5-15.84,6.96-26.94,19.89-14.58,36.36,18.56,24.72,115.14,56.1,146.77,62.89,82.16,17.65,152.89,2.18,231.43-22.46,54.98-17.25,130.36-44.86,168.52-89.18,25.27-29.35,31.42-69.3,44.38-104.84l-243.09,42.99-2,3.82c-1.45,15.08-2.76,30.11-6.03,44.92-31.75,143.69-186.99,93.71-283.19,53.84l1.47-2.15c82.39-23.86,163.75-50.91,245.03-78.2,5.91-3.48,5.08-25.81,7.22-33.55,3.45-12.47,12.22-19.65,23.97-24.08l282.88-49.24c14.15,3.11,20.4,11.87,18.9,26.37l-29.13,88.06v.02ZM841.24,457.54l-19.61,14.59c-113.51,75.99-355.25,76.96-485.87,53.37-58.02-10.48-91.56-24.33-143.96-48.22-1.22-.56-3.68-1.88-4.26-.11,9.51,23.92,8.86,56.35,22.36,78.1,28.12,45.3,113.96,67.69,163.71,76.52,72.61,12.88,148.98,14.98,222.29,7.73,63.62-6.3,204.67-30.25,226.3-101.29,7.88-25.88,11.16-54.64,19.03-80.69h0ZM806.3,607.51l-30.5,18.26c-131.73,66.26-405.38,65.51-535.38-4.91-6.49-3.51-12.31-8.25-18.62-11.96-1.12-.66-2.56-2.94-3.72-.65,11.55,32.54,8.2,71.49,34.17,96.87,59.84,58.47,212.94,70.07,292.78,66.97,63.99-2.48,191.09-21.71,233.65-73.56,19.02-23.17,17.88-63.15,27.62-91.02h0ZM774.26,744.37c-13.76,6.59-26.7,15.08-40.78,21.08-119.06,50.77-329.26,50.83-447.48-2.37-12.39-5.57-23.46-13.36-35.88-18.71,6.11,30.5,22.34,54.66,47.59,72.51,97.85,69.2,342.24,69.95,436.47-5.6,21.95-17.59,34.7-39.15,40.08-66.92h0Z"/>
<rect fill="#3b82f6" x="468.16" y="171.76" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
<rect fill="#3b82f6" x="593.35" y="118.61" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
<rect fill="#3b82f6" x="361.93" y="250.32" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1024 1024">
<!-- Generator: Adobe Illustrator 29.7.1, SVG Export Plug-In . SVG Version: 2.1.1 Build 8) -->
<path fill="#3b82f6" d="M797.56,348.33c30.91,6.66,83.06,31.07,87.21,66.41,3.15,26.85-13.06,79.89-19.48,108.33-18.08,80.05-35.49,169.43-58.24,247.51-37.84,129.87-259.97,143.84-369.81,131-79.98-9.34-191.79-42.13-218.72-127.8l-79.09-341.68c-6.97-50.68,49.68-73.96,89.21-85.61,54.67-16.12,110.4-16.62,167.08-15.62l-45.47,16.39c-44.91,18.53-101.62,26.35-145.23,45.5-15.84,6.96-26.94,19.89-14.58,36.36,18.56,24.72,115.14,56.1,146.77,62.89,82.16,17.65,152.89,2.18,231.43-22.46,54.98-17.25,130.36-44.86,168.52-89.18,25.27-29.35,31.42-69.3,44.38-104.84l-243.09,42.99-2,3.82c-1.45,15.08-2.76,30.11-6.03,44.92-31.75,143.69-186.99,93.71-283.19,53.84l1.47-2.15c82.39-23.86,163.75-50.91,245.03-78.2,5.91-3.48,5.08-25.81,7.22-33.55,3.45-12.47,12.22-19.65,23.97-24.08l282.88-49.24c14.15,3.11,20.4,11.87,18.9,26.37l-29.13,88.06v.02ZM841.24,457.54l-19.61,14.59c-113.51,75.99-355.25,76.96-485.87,53.37-58.02-10.48-91.56-24.33-143.96-48.22-1.22-.56-3.68-1.88-4.26-.11,9.51,23.92,8.86,56.35,22.36,78.1,28.12,45.3,113.96,67.69,163.71,76.52,72.61,12.88,148.98,14.98,222.29,7.73,63.62-6.3,204.67-30.25,226.3-101.29,7.88-25.88,11.16-54.64,19.03-80.69h0ZM806.3,607.51l-30.5,18.26c-131.73,66.26-405.38,65.51-535.38-4.91-6.49-3.51-12.31-8.25-18.62-11.96-1.12-.66-2.56-2.94-3.72-.65,11.55,32.54,8.2,71.49,34.17,96.87,59.84,58.47,212.94,70.07,292.78,66.97,63.99-2.48,191.09-21.71,233.65-73.56,19.02-23.17,17.88-63.15,27.62-91.02h0ZM774.26,744.37c-13.76,6.59-26.7,15.08-40.78,21.08-119.06,50.77-329.26,50.83-447.48-2.37-12.39-5.57-23.46-13.36-35.88-18.71,6.11,30.5,22.34,54.66,47.59,72.51,97.85,69.2,342.24,69.95,436.47-5.6,21.95-17.59,34.7-39.15,40.08-66.92h0Z"/>
<rect fill="#3b82f6" x="468.16" y="171.76" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
<rect fill="#3b82f6" x="593.35" y="118.61" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
<rect fill="#3b82f6" x="361.93" y="250.32" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

-6
View File
@@ -1,6 +0,0 @@
{
"name": "Trackeep",
"displayName": "Trackeep",
"version": "1.0.0",
"description": "Productivity and knowledge management mobile app"
}
-15
View File
@@ -1,15 +0,0 @@
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'module-resolver',
{
root: ['./src'],
extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json'],
alias: {
'@': './src',
},
},
],
],
};
-9
View File
@@ -1,9 +0,0 @@
/**
* Trackeep Mobile App
* React Native entry point
*/
import {AppRegistry} from 'react-native';
import App from './src/App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1024 1024">
<!-- Generator: Adobe Illustrator 29.7.1, SVG Export Plug-In . SVG Version: 2.1.1 Build 8) -->
<path fill="#3b82f6" d="M797.56,348.33c30.91,6.66,83.06,31.07,87.21,66.41,3.15,26.85-13.06,79.89-19.48,108.33-18.08,80.05-35.49,169.43-58.24,247.51-37.84,129.87-259.97,143.84-369.81,131-79.98-9.34-191.79-42.13-218.72-127.8l-79.09-341.68c-6.97-50.68,49.68-73.96,89.21-85.61,54.67-16.12,110.4-16.62,167.08-15.62l-45.47,16.39c-44.91,18.53-101.62,26.35-145.23,45.5-15.84,6.96-26.94,19.89-14.58,36.36,18.56,24.72,115.14,56.1,146.77,62.89,82.16,17.65,152.89,2.18,231.43-22.46,54.98-17.25,130.36-44.86,168.52-89.18,25.27-29.35,31.42-69.3,44.38-104.84l-243.09,42.99-2,3.82c-1.45,15.08-2.76,30.11-6.03,44.92-31.75,143.69-186.99,93.71-283.19,53.84l1.47-2.15c82.39-23.86,163.75-50.91,245.03-78.2,5.91-3.48,5.08-25.81,7.22-33.55,3.45-12.47,12.22-19.65,23.97-24.08l282.88-49.24c14.15,3.11,20.4,11.87,18.9,26.37l-29.13,88.06v.02ZM841.24,457.54l-19.61,14.59c-113.51,75.99-355.25,76.96-485.87,53.37-58.02-10.48-91.56-24.33-143.96-48.22-1.22-.56-3.68-1.88-4.26-.11,9.51,23.92,8.86,56.35,22.36,78.1,28.12,45.3,113.96,67.69,163.71,76.52,72.61,12.88,148.98,14.98,222.29,7.73,63.62-6.3,204.67-30.25,226.3-101.29,7.88-25.88,11.16-54.64,19.03-80.69h0ZM806.3,607.51l-30.5,18.26c-131.73,66.26-405.38,65.51-535.38-4.91-6.49-3.51-12.31-8.25-18.62-11.96-1.12-.66-2.56-2.94-3.72-.65,11.55,32.54,8.2,71.49,34.17,96.87,59.84,58.47,212.94,70.07,292.78,66.97,63.99-2.48,191.09-21.71,233.65-73.56,19.02-23.17,17.88-63.15,27.62-91.02h0ZM774.26,744.37c-13.76,6.59-26.7,15.08-40.78,21.08-119.06,50.77-329.26,50.83-447.48-2.37-12.39-5.57-23.46-13.36-35.88-18.71,6.11,30.5,22.34,54.66,47.59,72.51,97.85,69.2,342.24,69.95,436.47-5.6,21.95-17.59,34.7-39.15,40.08-66.92h0Z"/>
<rect fill="#3b82f6" x="468.16" y="171.76" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
<rect fill="#3b82f6" x="593.35" y="118.61" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
<rect fill="#3b82f6" x="361.93" y="250.32" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1024 1024">
<!-- Generator: Adobe Illustrator 29.7.1, SVG Export Plug-In . SVG Version: 2.1.1 Build 8) -->
<path fill="#3b82f6" d="M797.56,348.33c30.91,6.66,83.06,31.07,87.21,66.41,3.15,26.85-13.06,79.89-19.48,108.33-18.08,80.05-35.49,169.43-58.24,247.51-37.84,129.87-259.97,143.84-369.81,131-79.98-9.34-191.79-42.13-218.72-127.8l-79.09-341.68c-6.97-50.68,49.68-73.96,89.21-85.61,54.67-16.12,110.4-16.62,167.08-15.62l-45.47,16.39c-44.91,18.53-101.62,26.35-145.23,45.5-15.84,6.96-26.94,19.89-14.58,36.36,18.56,24.72,115.14,56.1,146.77,62.89,82.16,17.65,152.89,2.18,231.43-22.46,54.98-17.25,130.36-44.86,168.52-89.18,25.27-29.35,31.42-69.3,44.38-104.84l-243.09,42.99-2,3.82c-1.45,15.08-2.76,30.11-6.03,44.92-31.75,143.69-186.99,93.71-283.19,53.84l1.47-2.15c82.39-23.86,163.75-50.91,245.03-78.2,5.91-3.48,5.08-25.81,7.22-33.55,3.45-12.47,12.22-19.65,23.97-24.08l282.88-49.24c14.15,3.11,20.4,11.87,18.9,26.37l-29.13,88.06v.02ZM841.24,457.54l-19.61,14.59c-113.51,75.99-355.25,76.96-485.87,53.37-58.02-10.48-91.56-24.33-143.96-48.22-1.22-.56-3.68-1.88-4.26-.11,9.51,23.92,8.86,56.35,22.36,78.1,28.12,45.3,113.96,67.69,163.71,76.52,72.61,12.88,148.98,14.98,222.29,7.73,63.62-6.3,204.67-30.25,226.3-101.29,7.88-25.88,11.16-54.64,19.03-80.69h0ZM806.3,607.51l-30.5,18.26c-131.73,66.26-405.38,65.51-535.38-4.91-6.49-3.51-12.31-8.25-18.62-11.96-1.12-.66-2.56-2.94-3.72-.65,11.55,32.54,8.2,71.49,34.17,96.87,59.84,58.47,212.94,70.07,292.78,66.97,63.99-2.48,191.09-21.71,233.65-73.56,19.02-23.17,17.88-63.15,27.62-91.02h0ZM774.26,744.37c-13.76,6.59-26.7,15.08-40.78,21.08-119.06,50.77-329.26,50.83-447.48-2.37-12.39-5.57-23.46-13.36-35.88-18.71,6.11,30.5,22.34,54.66,47.59,72.51,97.85,69.2,342.24,69.95,436.47-5.6,21.95-17.59,34.7-39.15,40.08-66.92h0Z"/>
<rect fill="#3b82f6" x="468.16" y="171.76" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
<rect fill="#3b82f6" x="593.35" y="118.61" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
<rect fill="#3b82f6" x="361.93" y="250.32" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1024 1024">
<!-- Generator: Adobe Illustrator 29.7.1, SVG Export Plug-In . SVG Version: 2.1.1 Build 8) -->
<path fill="#3b82f6" d="M797.56,348.33c30.91,6.66,83.06,31.07,87.21,66.41,3.15,26.85-13.06,79.89-19.48,108.33-18.08,80.05-35.49,169.43-58.24,247.51-37.84,129.87-259.97,143.84-369.81,131-79.98-9.34-191.79-42.13-218.72-127.8l-79.09-341.68c-6.97-50.68,49.68-73.96,89.21-85.61,54.67-16.12,110.4-16.62,167.08-15.62l-45.47,16.39c-44.91,18.53-101.62,26.35-145.23,45.5-15.84,6.96-26.94,19.89-14.58,36.36,18.56,24.72,115.14,56.1,146.77,62.89,82.16,17.65,152.89,2.18,231.43-22.46,54.98-17.25,130.36-44.86,168.52-89.18,25.27-29.35,31.42-69.3,44.38-104.84l-243.09,42.99-2,3.82c-1.45,15.08-2.76,30.11-6.03,44.92-31.75,143.69-186.99,93.71-283.19,53.84l1.47-2.15c82.39-23.86,163.75-50.91,245.03-78.2,5.91-3.48,5.08-25.81,7.22-33.55,3.45-12.47,12.22-19.65,23.97-24.08l282.88-49.24c14.15,3.11,20.4,11.87,18.9,26.37l-29.13,88.06v.02ZM841.24,457.54l-19.61,14.59c-113.51,75.99-355.25,76.96-485.87,53.37-58.02-10.48-91.56-24.33-143.96-48.22-1.22-.56-3.68-1.88-4.26-.11,9.51,23.92,8.86,56.35,22.36,78.1,28.12,45.3,113.96,67.69,163.71,76.52,72.61,12.88,148.98,14.98,222.29,7.73,63.62-6.3,204.67-30.25,226.3-101.29,7.88-25.88,11.16-54.64,19.03-80.69h0ZM806.3,607.51l-30.5,18.26c-131.73,66.26-405.38,65.51-535.38-4.91-6.49-3.51-12.31-8.25-18.62-11.96-1.12-.66-2.56-2.94-3.72-.65,11.55,32.54,8.2,71.49,34.17,96.87,59.84,58.47,212.94,70.07,292.78,66.97,63.99-2.48,191.09-21.71,233.65-73.56,19.02-23.17,17.88-63.15,27.62-91.02h0ZM774.26,744.37c-13.76,6.59-26.7,15.08-40.78,21.08-119.06,50.77-329.26,50.83-447.48-2.37-12.39-5.57-23.46-13.36-35.88-18.71,6.11,30.5,22.34,54.66,47.59,72.51,97.85,69.2,342.24,69.95,436.47-5.6,21.95-17.59,34.7-39.15,40.08-66.92h0Z"/>
<rect fill="#3b82f6" x="468.16" y="171.76" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
<rect fill="#3b82f6" x="593.35" y="118.61" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
<rect fill="#3b82f6" x="361.93" y="250.32" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1024 1024">
<!-- Generator: Adobe Illustrator 29.7.1, SVG Export Plug-In . SVG Version: 2.1.1 Build 8) -->
<path fill="#3b82f6" d="M797.56,348.33c30.91,6.66,83.06,31.07,87.21,66.41,3.15,26.85-13.06,79.89-19.48,108.33-18.08,80.05-35.49,169.43-58.24,247.51-37.84,129.87-259.97,143.84-369.81,131-79.98-9.34-191.79-42.13-218.72-127.8l-79.09-341.68c-6.97-50.68,49.68-73.96,89.21-85.61,54.67-16.12,110.4-16.62,167.08-15.62l-45.47,16.39c-44.91,18.53-101.62,26.35-145.23,45.5-15.84,6.96-26.94,19.89-14.58,36.36,18.56,24.72,115.14,56.1,146.77,62.89,82.16,17.65,152.89,2.18,231.43-22.46,54.98-17.25,130.36-44.86,168.52-89.18,25.27-29.35,31.42-69.3,44.38-104.84l-243.09,42.99-2,3.82c-1.45,15.08-2.76,30.11-6.03,44.92-31.75,143.69-186.99,93.71-283.19,53.84l1.47-2.15c82.39-23.86,163.75-50.91,245.03-78.2,5.91-3.48,5.08-25.81,7.22-33.55,3.45-12.47,12.22-19.65,23.97-24.08l282.88-49.24c14.15,3.11,20.4,11.87,18.9,26.37l-29.13,88.06v.02ZM841.24,457.54l-19.61,14.59c-113.51,75.99-355.25,76.96-485.87,53.37-58.02-10.48-91.56-24.33-143.96-48.22-1.22-.56-3.68-1.88-4.26-.11,9.51,23.92,8.86,56.35,22.36,78.1,28.12,45.3,113.96,67.69,163.71,76.52,72.61,12.88,148.98,14.98,222.29,7.73,63.62-6.3,204.67-30.25,226.3-101.29,7.88-25.88,11.16-54.64,19.03-80.69h0ZM806.3,607.51l-30.5,18.26c-131.73,66.26-405.38,65.51-535.38-4.91-6.49-3.51-12.31-8.25-18.62-11.96-1.12-.66-2.56-2.94-3.72-.65,11.55,32.54,8.2,71.49,34.17,96.87,59.84,58.47,212.94,70.07,292.78,66.97,63.99-2.48,191.09-21.71,233.65-73.56,19.02-23.17,17.88-63.15,27.62-91.02h0ZM774.26,744.37c-13.76,6.59-26.7,15.08-40.78,21.08-119.06,50.77-329.26,50.83-447.48-2.37-12.39-5.57-23.46-13.36-35.88-18.71,6.11,30.5,22.34,54.66,47.59,72.51,97.85,69.2,342.24,69.95,436.47-5.6,21.95-17.59,34.7-39.15,40.08-66.92h0Z"/>
<rect fill="#3b82f6" x="468.16" y="171.76" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
<rect fill="#3b82f6" x="593.35" y="118.61" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
<rect fill="#3b82f6" x="361.93" y="250.32" width="53.15" height="53.15" rx="5.6" ry="5.6"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

-21
View File
@@ -1,21 +0,0 @@
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
const defaultConfig = getDefaultConfig(__dirname);
const config = {
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
resolver: {
alias: {
'@': './src',
},
},
};
module.exports = mergeConfig(defaultConfig, config);
-12563
View File
File diff suppressed because it is too large Load Diff
-64
View File
@@ -1,64 +0,0 @@
{
"name": "trackeep-mobile",
"version": "1.0.0",
"description": "Trackeep mobile app for productivity and knowledge management",
"main": "index.js",
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
"build:android": "cd android && ./gradlew assembleRelease",
"build:ios": "react-native run-ios --configuration Release"
},
"dependencies": {
"@react-native-async-storage/async-storage": "^1.19.5",
"@react-native-community/netinfo": "^11.4.1",
"@react-navigation/bottom-tabs": "^6.5.11",
"@react-navigation/drawer": "^6.6.6",
"@react-navigation/native": "^6.1.9",
"@react-navigation/native-stack": "^6.9.26",
"@react-navigation/stack": "^6.3.20",
"@types/react-native-push-notification": "^8.1.4",
"@types/react-native-vector-icons": "^6.4.18",
"axios": "^1.6.2",
"react": "18.2.0",
"react-native": "0.72.6",
"react-native-background-timer": "^2.4.1",
"react-native-camera": "^4.2.1",
"react-native-gesture-handler": "^2.13.4",
"react-native-keychain": "^8.1.3",
"react-native-paper": "^5.11.1",
"react-native-permissions": "^3.10.1",
"react-native-push-notification": "^8.1.1",
"react-native-reanimated": "^3.5.4",
"react-native-safe-area-context": "^4.7.4",
"react-native-screens": "^3.25.0",
"react-native-sqlite-storage": "^6.0.1",
"react-native-svg": "^13.14.0",
"react-native-vector-icons": "^10.0.2",
"react-native-vision-camera": "^3.3.5",
"react-native-voice": "^0.3.0"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@babel/preset-env": "^7.20.0",
"@babel/runtime": "^7.20.0",
"@react-native/eslint-config": "^0.72.2",
"@react-native/metro-config": "^0.72.11",
"@tsconfig/react-native": "^3.0.0",
"@types/react": "^18.0.24",
"@types/react-test-renderer": "^18.0.0",
"babel-jest": "^29.2.1",
"eslint": "^8.19.0",
"jest": "^29.2.1",
"metro-react-native-babel-preset": "0.76.8",
"prettier": "^2.4.1",
"react-test-renderer": "18.2.0",
"typescript": "4.8.4"
},
"jest": {
"preset": "react-native"
}
}
-93
View File
@@ -1,93 +0,0 @@
import React, { useEffect, useState } from 'react';
import {
NavigationContainer,
DefaultTheme as NavigationDefaultTheme,
DarkTheme as NavigationDarkTheme,
} from '@react-navigation/native';
import {
Provider as PaperProvider,
DefaultTheme as PaperDefaultTheme,
MD3DarkTheme as PaperDarkTheme,
} from 'react-native-paper';
import { StatusBar } from 'react-native';
import { AuthProvider } from './services/AuthContext';
import { OfflineProvider } from './services/OfflineContext';
import { NotificationProvider } from './services/NotificationContext';
import { CameraProvider } from './services/CameraContext';
import { VoiceProvider } from './services/VoiceContext';
import { ServerConfigProvider } from './services/ServerConfigContext';
import { RealtimeSyncProvider } from './services/RealtimeSyncContext';
import AppNavigator from './navigation/AppNavigator';
import { loadTheme } from './utils/storage';
const CombinedDefaultTheme = {
...NavigationDefaultTheme,
...PaperDefaultTheme,
colors: {
...NavigationDefaultTheme.colors,
...PaperDefaultTheme.colors,
},
};
const CombinedDarkTheme = {
...NavigationDarkTheme,
...PaperDarkTheme,
colors: {
...NavigationDarkTheme.colors,
...PaperDarkTheme.colors,
},
};
const App: React.FC = () => {
const [isDarkTheme, setIsDarkTheme] = useState(false);
const [isThemeLoaded, setIsThemeLoaded] = useState(false);
useEffect(() => {
const initializeTheme = async () => {
try {
const savedTheme = await loadTheme();
setIsDarkTheme(savedTheme === 'dark');
} catch (error) {
console.error('Error loading theme:', error);
} finally {
setIsThemeLoaded(true);
}
};
initializeTheme();
}, []);
const theme = isDarkTheme ? CombinedDarkTheme : CombinedDefaultTheme;
if (!isThemeLoaded) {
return null;
}
return (
<PaperProvider theme={theme}>
<NavigationContainer theme={theme}>
<StatusBar
barStyle={isDarkTheme ? 'light-content' : 'dark-content'}
backgroundColor={theme.colors.background}
/>
<ServerConfigProvider>
<RealtimeSyncProvider>
<AuthProvider>
<NotificationProvider>
<CameraProvider>
<VoiceProvider>
<OfflineProvider>
<AppNavigator />
</OfflineProvider>
</VoiceProvider>
</CameraProvider>
</NotificationProvider>
</AuthProvider>
</RealtimeSyncProvider>
</ServerConfigProvider>
</NavigationContainer>
</PaperProvider>
);
};
export default App;
@@ -1,40 +0,0 @@
import React from 'react';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { useAuth } from '../services/AuthContext';
import { useServerConfig } from '../services/ServerConfigContext';
import AuthNavigator from './AuthNavigator';
import TabNavigator from './TabNavigator';
import LoadingScreen from '../screens/LoadingScreen';
import ServerSetupScreen from '../screens/ServerSetupScreen';
export type RootStackParamList = {
Auth: undefined;
Main: undefined;
Loading: undefined;
ServerSetup: undefined;
};
const Stack = createNativeStackNavigator<RootStackParamList>();
const AppNavigator: React.FC = () => {
const { isAuthenticated, isLoading } = useAuth();
const { isConfigured, isLoading: configLoading } = useServerConfig();
if (isLoading || configLoading) {
return <LoadingScreen />;
}
return (
<Stack.Navigator screenOptions={{ headerShown: false }}>
{!isConfigured ? (
<Stack.Screen name="ServerSetup" component={ServerSetupScreen} />
) : isAuthenticated ? (
<Stack.Screen name="Main" component={TabNavigator} />
) : (
<Stack.Screen name="Auth" component={AuthNavigator} />
)}
</Stack.Navigator>
);
};
export default AppNavigator;
@@ -1,27 +0,0 @@
import React from 'react';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import LoginScreen from '../screens/auth/LoginScreen';
import RegisterScreen from '../screens/auth/RegisterScreen';
export type AuthStackParamList = {
Login: undefined;
Register: undefined;
};
const Stack = createNativeStackNavigator<AuthStackParamList>();
const AuthNavigator: React.FC = () => {
return (
<Stack.Navigator
screenOptions={{
headerShown: false,
gestureEnabled: false,
}}
>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Register" component={RegisterScreen} />
</Stack.Navigator>
);
};
export default AuthNavigator;
@@ -1,129 +0,0 @@
import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { useOffline } from '../services/OfflineContext';
import { useTheme } from 'react-native-paper';
import DashboardScreen from '../screens/DashboardScreen';
import BookmarksScreen from '../screens/BookmarksScreen';
import TasksScreen from '../screens/TasksScreen';
import NotesScreen from '../screens/NotesScreen';
import TimeTrackingScreen from '../screens/TimeTrackingScreen';
import SearchScreen from '../screens/SearchScreen';
import SettingsScreen from '../screens/SettingsScreen';
import AIAssistantScreen from '../screens/AIAssistantScreen';
export type MainTabParamList = {
Dashboard: undefined;
Bookmarks: undefined;
Tasks: undefined;
Notes: undefined;
TimeTracking: undefined;
Search: undefined;
AIAssistant: undefined;
Settings: undefined;
};
const Tab = createBottomTabNavigator<MainTabParamList>();
const TabNavigator: React.FC = () => {
const { pendingChanges } = useOffline();
const theme = useTheme();
return (
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ color, size }) => {
let iconName: string;
switch (route.name) {
case 'Dashboard':
iconName = 'view-dashboard';
break;
case 'Bookmarks':
iconName = 'bookmark';
break;
case 'Tasks':
iconName = 'check-circle';
break;
case 'Notes':
iconName = 'note-text';
break;
case 'TimeTracking':
iconName = 'timer';
break;
case 'Search':
iconName = 'magnify';
break;
case 'AIAssistant':
iconName = 'robot';
break;
case 'Settings':
iconName = 'cog';
break;
default:
iconName = 'help-circle';
}
return <Icon name={iconName} size={size} color={color} />;
},
tabBarActiveTintColor: theme.colors.primary,
tabBarInactiveTintColor: 'gray',
tabBarStyle: {
backgroundColor: theme.colors.surface,
borderTopColor: theme.colors.outline,
},
headerStyle: {
backgroundColor: theme.colors.surface,
},
headerTintColor: theme.colors.onSurface,
})}
>
<Tab.Screen
name="Dashboard"
component={DashboardScreen}
options={{
title: 'Dashboard',
tabBarBadge: pendingChanges > 0 ? pendingChanges : undefined,
}}
/>
<Tab.Screen
name="Bookmarks"
component={BookmarksScreen}
options={{ title: 'Bookmarks' }}
/>
<Tab.Screen
name="Tasks"
component={TasksScreen}
options={{ title: 'Tasks' }}
/>
<Tab.Screen
name="Notes"
component={NotesScreen}
options={{ title: 'Notes' }}
/>
<Tab.Screen
name="TimeTracking"
component={TimeTrackingScreen}
options={{ title: 'Time' }}
/>
<Tab.Screen
name="Search"
component={SearchScreen}
options={{ title: 'Search' }}
/>
<Tab.Screen
name="AIAssistant"
component={AIAssistantScreen}
options={{ title: 'AI' }}
/>
<Tab.Screen
name="Settings"
component={SettingsScreen}
options={{ title: 'Settings' }}
/>
</Tab.Navigator>
);
};
export default TabNavigator;
@@ -1,400 +0,0 @@
import React, { useState, useEffect } from 'react';
import {
View,
StyleSheet,
ScrollView,
KeyboardAvoidingView,
Platform,
} from 'react-native';
import {
Text,
Title,
Paragraph,
TextInput,
Button,
Avatar,
Chip,
} from 'react-native-paper';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useRealtimeUpdates } from '../services/RealtimeSyncContext';
import { useServerConfig } from '../services/ServerConfigContext';
interface Message {
id: string;
text: string;
sender: 'user' | 'ai';
timestamp: Date;
type?: 'text' | 'recommendation' | 'analysis';
}
const AIAssistantScreen: React.FC = () => {
const [messages, setMessages] = useState<Message[]>([]);
const [inputText, setInputText] = useState('');
const [isLoading, setIsLoading] = useState(false);
const { config } = useServerConfig();
const [suggestions] = useState([
'Help me organize my tasks',
'Suggest bookmarks for learning React',
'Analyze my productivity patterns',
'Create a study plan',
]);
useEffect(() => {
// Initialize with welcome message
setMessages([
{
id: '1',
text: "Hello! I'm your AI assistant. I can help you organize tasks, suggest bookmarks, analyze your productivity, and much more. How can I assist you today?",
sender: 'ai',
timestamp: new Date(),
type: 'text',
},
]);
}, []);
// Listen for real-time AI updates
useRealtimeUpdates((data) => {
if (data.type === 'ai_response') {
const newMessage: Message = {
id: Date.now().toString(),
text: data.response,
sender: 'ai',
timestamp: new Date(),
type: data.responseType,
};
setMessages(prev => [...prev, newMessage]);
setIsLoading(false);
}
});
const handleSendMessage = async () => {
if (!inputText.trim()) return;
const userMessage: Message = {
id: Date.now().toString(),
text: inputText,
sender: 'user',
timestamp: new Date(),
};
setMessages(prev => [...prev, userMessage]);
setInputText('');
setIsLoading(true);
try {
// Call LongCat AI API
const response = await fetch(`${config?.baseUrl}/api/ai/chat`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${await getAuthToken()}`,
},
body: JSON.stringify({
message: inputText,
context: 'trackeep_assistant',
}),
});
if (response.ok) {
const data = await response.json();
const aiResponse: Message = {
id: (Date.now() + 1).toString(),
text: data.response,
sender: 'ai',
timestamp: new Date(),
type: data.type || 'text',
};
setMessages(prev => [...prev, aiResponse]);
} else {
// Fallback to mock response
const mockResponse: Message = {
id: (Date.now() + 1).toString(),
text: generateMockResponse(inputText),
sender: 'ai',
timestamp: new Date(),
type: 'text',
};
setMessages(prev => [...prev, mockResponse]);
}
} catch (error) {
console.error('Error calling AI API:', error);
// Fallback to mock response
const mockResponse: Message = {
id: (Date.now() + 1).toString(),
text: generateMockResponse(inputText),
sender: 'ai',
timestamp: new Date(),
type: 'text',
};
setMessages(prev => [...prev, mockResponse]);
} finally {
setIsLoading(false);
}
};
const getAuthToken = async (): Promise<string | null> => {
try {
const authData = await AsyncStorage.getItem('trackeep_auth_token');
return authData;
} catch (error) {
console.error('Error getting auth token:', error);
return null;
}
};
const generateMockResponse = (userInput: string): string => {
const input = userInput.toLowerCase();
if (input.includes('task') || input.includes('organize')) {
return "I can help you organize your tasks! Based on your current tasks, I suggest prioritizing the high-priority items first. Would you like me to create a schedule for you?";
} else if (input.includes('bookmark') || input.includes('learn')) {
return "Great! I can suggest relevant bookmarks for your learning goals. I see you're interested in React - here are some top resources I recommend...";
} else if (input.includes('productivity') || input.includes('analyze')) {
return "Looking at your activity patterns, you're most productive in the morning. I suggest scheduling important tasks between 9-11 AM for better results.";
} else if (input.includes('study') || input.includes('plan')) {
return "I can create a personalized study plan for you! Based on your current notes and bookmarks, here's a structured learning path...";
} else {
return "I understand you need help with that. Let me analyze your current data and provide you with personalized recommendations.";
}
};
const handleSuggestionPress = (suggestion: string) => {
setInputText(suggestion);
};
const formatTime = (date: Date): string => {
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
};
const renderMessage = (message: Message) => (
<View key={message.id} style={[
styles.messageContainer,
message.sender === 'user' ? styles.userMessage : styles.aiMessage,
]}>
{message.sender === 'ai' && (
<Avatar.Text
size={32}
label="AI"
style={styles.avatar}
/>
)}
<View style={[
styles.messageBubble,
message.sender === 'user' ? styles.userBubble : styles.aiBubble,
]}>
<Text style={[
styles.messageText,
message.sender === 'user' ? styles.userText : styles.aiText,
]}>
{message.text}
</Text>
<Text style={styles.timestamp}>
{formatTime(message.timestamp)}
</Text>
</View>
{message.sender === 'user' && (
<Avatar.Text
size={32}
label="U"
style={styles.avatar}
/>
)}
</View>
);
return (
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.container}
>
<View style={styles.header}>
<Title style={styles.title}>AI Assistant</Title>
<Paragraph style={styles.subtitle}>
Your personal productivity companion
</Paragraph>
</View>
<ScrollView
style={styles.messagesContainer}
contentContainerStyle={styles.messagesContent}
>
{messages.map(renderMessage)}
{isLoading && (
<View style={[styles.messageContainer, styles.aiMessage]}>
<Avatar.Text
size={32}
label="AI"
style={styles.avatar}
/>
<View style={[styles.messageBubble, styles.aiBubble]}>
<Text style={styles.aiText}>Thinking...</Text>
</View>
</View>
)}
</ScrollView>
{/* Suggestions */}
{messages.length === 1 && (
<View style={styles.suggestionsContainer}>
<Text style={styles.suggestionsTitle}>Try asking:</Text>
<View style={styles.suggestionsList}>
{suggestions.map((suggestion, index) => (
<Chip
key={index}
onPress={() => handleSuggestionPress(suggestion)}
style={styles.suggestionChip}
textStyle={styles.suggestionText}
>
{suggestion}
</Chip>
))}
</View>
</View>
)}
{/* Input Area */}
<View style={styles.inputContainer}>
<TextInput
value={inputText}
onChangeText={setInputText}
placeholder="Ask me anything..."
multiline
maxLength={500}
style={styles.textInput}
right={
<TextInput.Icon
icon="send"
onPress={handleSendMessage}
disabled={!inputText.trim() || isLoading}
/>
}
/>
<Button
mode="contained"
onPress={handleSendMessage}
disabled={!inputText.trim() || isLoading}
loading={isLoading}
style={styles.sendButton}
>
Send
</Button>
</View>
</KeyboardAvoidingView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
header: {
padding: 16,
backgroundColor: '#fff',
borderBottomWidth: 1,
borderBottomColor: '#e0e0e0',
},
title: {
fontSize: 24,
fontWeight: 'bold',
color: '#6200ee',
},
subtitle: {
color: '#666',
marginTop: 4,
},
messagesContainer: {
flex: 1,
},
messagesContent: {
padding: 16,
},
messageContainer: {
flexDirection: 'row',
marginBottom: 16,
alignItems: 'flex-end',
},
userMessage: {
justifyContent: 'flex-end',
},
aiMessage: {
justifyContent: 'flex-start',
},
avatar: {
marginHorizontal: 8,
backgroundColor: '#6200ee',
},
messageBubble: {
maxWidth: '70%',
padding: 12,
borderRadius: 16,
minHeight: 40,
},
userBubble: {
backgroundColor: '#6200ee',
borderBottomRightRadius: 4,
},
aiBubble: {
backgroundColor: '#fff',
borderBottomLeftRadius: 4,
borderWidth: 1,
borderColor: '#e0e0e0',
},
messageText: {
fontSize: 16,
lineHeight: 20,
},
userText: {
color: '#fff',
},
aiText: {
color: '#333',
},
timestamp: {
fontSize: 11,
color: '#999',
marginTop: 4,
alignSelf: 'flex-end',
},
suggestionsContainer: {
padding: 16,
backgroundColor: '#fff',
borderTopWidth: 1,
borderTopColor: '#e0e0e0',
},
suggestionsTitle: {
fontSize: 14,
fontWeight: '600',
color: '#666',
marginBottom: 8,
},
suggestionsList: {
flexDirection: 'row',
flexWrap: 'wrap',
gap: 8,
},
suggestionChip: {
backgroundColor: '#f0f0f0',
},
suggestionText: {
fontSize: 12,
color: '#333',
},
inputContainer: {
padding: 16,
backgroundColor: '#fff',
borderTopWidth: 1,
borderTopColor: '#e0e0e0',
},
textInput: {
marginBottom: 8,
backgroundColor: '#f8f8f8',
},
sendButton: {
backgroundColor: '#6200ee',
},
});
export default AIAssistantScreen;
@@ -1,119 +0,0 @@
import React from 'react';
import { View, StyleSheet, FlatList } from 'react-native';
import { Text, Card, Title, Paragraph, FAB, Searchbar } from 'react-native-paper';
const BookmarksScreen: React.FC = () => {
const [searchQuery, setSearchQuery] = React.useState('');
const [bookmarks] = React.useState([
{
id: '1',
title: 'React Native Documentation',
url: 'https://reactnative.dev',
description: 'Official React Native documentation',
tags: ['react', 'mobile', 'documentation'],
isFavorite: true,
createdAt: new Date(),
},
{
id: '2',
title: 'TypeScript Handbook',
url: 'https://www.typescriptlang.org/docs',
description: 'Learn TypeScript from the official handbook',
tags: ['typescript', 'programming', 'tutorial'],
isFavorite: false,
createdAt: new Date(),
},
]);
const onChangeSearch = (query: string) => setSearchQuery(query);
const renderBookmark = ({ item }: any) => (
<Card style={styles.card}>
<Card.Content>
<Title numberOfLines={1}>{item.title}</Title>
<Paragraph numberOfLines={2}>{item.description}</Paragraph>
<Text style={styles.url}>{item.url}</Text>
<View style={styles.tagsContainer}>
{item.tags.map((tag: string, index: number) => (
<Text key={index} style={styles.tag}>
#{tag}
</Text>
))}
</View>
</Card.Content>
</Card>
);
return (
<View style={styles.container}>
<Searchbar
placeholder="Search bookmarks..."
onChangeText={onChangeSearch}
value={searchQuery}
style={styles.searchBar}
/>
<FlatList
data={bookmarks}
renderItem={renderBookmark}
keyExtractor={(item) => item.id}
contentContainerStyle={styles.list}
showsVerticalScrollIndicator={false}
/>
<FAB
icon="bookmark-plus"
style={styles.fab}
onPress={() => console.log('Add bookmark')}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
searchBar: {
margin: 16,
marginBottom: 8,
},
list: {
paddingHorizontal: 16,
paddingBottom: 80,
},
card: {
marginBottom: 12,
elevation: 2,
},
url: {
color: '#6200ee',
fontSize: 12,
marginTop: 8,
},
tagsContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
marginTop: 8,
},
tag: {
backgroundColor: '#e3f2fd',
color: '#1976d2',
paddingHorizontal: 8,
paddingVertical: 4,
borderRadius: 12,
fontSize: 10,
marginRight: 4,
marginBottom: 4,
},
fab: {
position: 'absolute',
margin: 16,
right: 0,
bottom: 0,
backgroundColor: '#6200ee',
},
});
export default BookmarksScreen;
@@ -1,444 +0,0 @@
import React, { useState, useEffect } from 'react';
import { View, StyleSheet, ScrollView, RefreshControl, Dimensions } from 'react-native';
import { Text, Card, Title, Paragraph, Button, FAB, Avatar, Chip, ProgressBar } from 'react-native-paper';
import { useAuth } from '../services/AuthContext';
import { useOffline } from '../services/OfflineContext';
import { useRealtimeSync, useRealtimeUpdates } from '../services/RealtimeSyncContext';
import { bookmarksAPI, tasksAPI, notesAPI } from '../services/api';
interface QuickStats {
totalBookmarks: number;
totalTasks: number;
totalNotes: number;
completedTasks: number;
recentActivity: number;
}
interface RecentActivity {
id: string;
type: 'bookmark' | 'task' | 'note';
action: string;
title: string;
timestamp: string;
}
const { width } = Dimensions.get('window');
const DashboardScreen: React.FC = () => {
const { user } = useAuth();
const { isOnline, pendingChanges, syncNow } = useOffline();
const { isSyncing, lastSyncTime } = useRealtimeSync();
const [stats, setStats] = useState<QuickStats>({
totalBookmarks: 0,
totalTasks: 0,
totalNotes: 0,
completedTasks: 0,
recentActivity: 0,
});
const [recentActivity, setRecentActivity] = useState<RecentActivity[]>([]);
const [refreshing, setRefreshing] = useState(false);
useEffect(() => {
loadDashboardData();
}, []);
// Listen for real-time updates
useRealtimeUpdates((data) => {
console.log('Dashboard received real-time update:', data);
loadDashboardData();
});
const loadDashboardData = async () => {
try {
const [bookmarksRes, tasksRes, notesRes] = await Promise.all([
bookmarksAPI.getBookmarks(),
tasksAPI.getTasks(),
notesAPI.getNotes(),
]);
if (bookmarksRes.success && tasksRes.success && notesRes.success) {
const bookmarks = bookmarksRes.data || [];
const tasks = tasksRes.data || [];
const notes = notesRes.data || [];
const completedTasks = tasks.filter(task => (task as any).completed).length;
setStats({
totalBookmarks: bookmarks.length,
totalTasks: tasks.length,
totalNotes: notes.length,
completedTasks,
recentActivity: 5, // Mock recent activity count
});
// Generate mock recent activity
const activity: RecentActivity[] = [
{
id: '1',
type: 'bookmark',
action: 'Added',
title: bookmarks[0]?.title || 'New bookmark',
timestamp: '2 hours ago',
},
{
id: '2',
type: 'task',
action: 'Completed',
title: tasks[0]?.title || 'New task',
timestamp: '3 hours ago',
},
{
id: '3',
type: 'note',
action: 'Created',
title: notes[0]?.title || 'New note',
timestamp: '5 hours ago',
},
];
setRecentActivity(activity);
}
} catch (error) {
console.error('Error loading dashboard data:', error);
}
};
const onRefresh = async () => {
setRefreshing(true);
await loadDashboardData();
if (isOnline && pendingChanges > 0) {
await syncNow();
}
setRefreshing(false);
};
const getTaskCompletionPercentage = () => {
if (stats.totalTasks === 0) return 0;
return Math.round((stats.completedTasks / stats.totalTasks) * 100);
};
const formatLastSync = () => {
if (!lastSyncTime) return 'Never';
const now = Date.now();
const diff = now - lastSyncTime;
const minutes = Math.floor(diff / 60000);
if (minutes < 1) return 'Just now';
if (minutes < 60) return `${minutes}m ago`;
const hours = Math.floor(minutes / 60);
if (hours < 24) return `${hours}h ago`;
return `${Math.floor(hours / 24)}d ago`;
};
return (
<View style={styles.container}>
<ScrollView
style={styles.scrollView}
showsVerticalScrollIndicator={false}
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
}
>
{/* Header Section */}
<View style={styles.header}>
<View style={styles.userSection}>
<Avatar.Text
size={60}
label={user?.name?.charAt(0).toUpperCase() || 'U'}
style={styles.avatar}
/>
<View style={styles.userInfo}>
<Title style={styles.welcomeText}>
Welcome back, {user?.name || 'User'}!
</Title>
<Paragraph style={styles.subtitle}>
{isOnline ? '🟢 Connected' : '🔴 Offline'}
{isSyncing ? ' Syncing...' : ` Last sync: ${formatLastSync()}`}
</Paragraph>
</View>
</View>
</View>
{/* Quick Stats Cards */}
<View style={styles.statsGrid}>
<Card style={[styles.statCard, { backgroundColor: '#e3f2fd' }]}>
<Card.Content style={styles.statContent}>
<Text style={[styles.statNumber, { color: '#1976d2' }]}>
{stats.totalBookmarks}
</Text>
<Text style={styles.statLabel}>Bookmarks</Text>
</Card.Content>
</Card>
<Card style={[styles.statCard, { backgroundColor: '#e8f5e8' }]}>
<Card.Content style={styles.statContent}>
<Text style={[styles.statNumber, { color: '#388e3c' }]}>
{stats.totalTasks}
</Text>
<Text style={styles.statLabel}>Tasks</Text>
</Card.Content>
</Card>
<Card style={[styles.statCard, { backgroundColor: '#fff3e0' }]}>
<Card.Content style={styles.statContent}>
<Text style={[styles.statNumber, { color: '#f57c00' }]}>
{stats.totalNotes}
</Text>
<Text style={styles.statLabel}>Notes</Text>
</Card.Content>
</Card>
</View>
{/* Task Progress */}
<Card style={styles.card}>
<Card.Content>
<Title style={styles.cardTitle}>Task Progress</Title>
<View style={styles.progressContainer}>
<Text style={styles.progressText}>
{stats.completedTasks} of {stats.totalTasks} tasks completed
</Text>
<ProgressBar
progress={getTaskCompletionPercentage() / 100}
color="#4caf50"
style={styles.progressBar}
/>
<Text style={styles.progressPercentage}>
{getTaskCompletionPercentage()}%
</Text>
</View>
</Card.Content>
</Card>
{/* Recent Activity */}
<Card style={styles.card}>
<Card.Content>
<Title style={styles.cardTitle}>Recent Activity</Title>
{recentActivity.length > 0 ? (
recentActivity.map((activity) => (
<View key={activity.id} style={styles.activityItem}>
<View style={styles.activityIcon}>
<Text style={styles.activityEmoji}>
{activity.type === 'bookmark' ? '🔖' :
activity.type === 'task' ? '✅' : '📝'}
</Text>
</View>
<View style={styles.activityContent}>
<Text style={styles.activityTitle}>
{activity.action} {activity.title}
</Text>
<Text style={styles.activityTime}>
{activity.timestamp}
</Text>
</View>
</View>
))
) : (
<Paragraph style={styles.emptyText}>No recent activity</Paragraph>
)}
</Card.Content>
</Card>
{/* Sync Status */}
{!isOnline && pendingChanges > 0 && (
<Card style={[styles.card, styles.offlineCard]}>
<Card.Content>
<Title style={styles.cardTitle}>Offline Mode</Title>
<Paragraph>
You have {pendingChanges} changes pending sync
</Paragraph>
<Button
mode="outlined"
onPress={syncNow}
style={styles.syncButton}
disabled={!isOnline || isSyncing}
loading={isSyncing}
>
{isSyncing ? 'Syncing...' : 'Sync Now'}
</Button>
</Card.Content>
</Card>
)}
{/* Quick Actions */}
<Card style={styles.card}>
<Card.Content>
<Title style={styles.cardTitle}>Quick Actions</Title>
<View style={styles.quickActions}>
<Chip
icon="bookmark-plus"
onPress={() => console.log('Add bookmark')}
style={styles.actionChip}
>
Add Bookmark
</Chip>
<Chip
icon="plus"
onPress={() => console.log('Add task')}
style={styles.actionChip}
>
Add Task
</Chip>
<Chip
icon="note-plus"
onPress={() => console.log('Add note')}
style={styles.actionChip}
>
Add Note
</Chip>
</View>
</Card.Content>
</Card>
</ScrollView>
<FAB
icon="plus"
style={styles.fab}
onPress={() => console.log('Add new item')}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
scrollView: {
flex: 1,
padding: 16,
},
header: {
marginBottom: 24,
},
userSection: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 16,
},
avatar: {
marginRight: 16,
backgroundColor: '#6200ee',
},
userInfo: {
flex: 1,
},
welcomeText: {
fontSize: 24,
fontWeight: 'bold',
},
subtitle: {
color: '#666',
marginTop: 4,
fontSize: 14,
},
statsGrid: {
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 20,
},
statCard: {
width: (width - 48) / 3,
elevation: 2,
},
statContent: {
alignItems: 'center',
paddingVertical: 16,
},
statNumber: {
fontSize: 24,
fontWeight: 'bold',
},
statLabel: {
fontSize: 12,
color: '#666',
marginTop: 4,
textAlign: 'center',
},
card: {
marginBottom: 16,
elevation: 2,
},
cardTitle: {
fontSize: 18,
marginBottom: 12,
color: '#333',
},
progressContainer: {
marginTop: 8,
},
progressText: {
fontSize: 14,
color: '#666',
marginBottom: 8,
},
progressBar: {
height: 8,
borderRadius: 4,
marginBottom: 8,
},
progressPercentage: {
fontSize: 16,
fontWeight: 'bold',
color: '#4caf50',
textAlign: 'center',
},
activityItem: {
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 8,
borderBottomWidth: 1,
borderBottomColor: '#f0f0f0',
},
activityIcon: {
marginRight: 12,
},
activityEmoji: {
fontSize: 20,
},
activityContent: {
flex: 1,
},
activityTitle: {
fontSize: 14,
fontWeight: '500',
color: '#333',
},
activityTime: {
fontSize: 12,
color: '#666',
marginTop: 2,
},
emptyText: {
textAlign: 'center',
color: '#666',
fontStyle: 'italic',
},
offlineCard: {
backgroundColor: '#fff3cd',
borderColor: '#ffeaa7',
borderWidth: 1,
},
syncButton: {
marginTop: 12,
},
quickActions: {
flexDirection: 'row',
flexWrap: 'wrap',
gap: 8,
},
actionChip: {
marginBottom: 8,
},
fab: {
position: 'absolute',
margin: 16,
right: 0,
bottom: 0,
backgroundColor: '#6200ee',
},
});
export default DashboardScreen;
@@ -1,28 +0,0 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { ActivityIndicator, Text } from 'react-native-paper';
const LoadingScreen: React.FC = () => {
return (
<View style={styles.container}>
<ActivityIndicator size="large" />
<Text style={styles.text}>Loading Trackeep...</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f5f5f5',
},
text: {
marginTop: 16,
fontSize: 16,
color: '#666',
},
});
export default LoadingScreen;
@@ -1,104 +0,0 @@
import React from 'react';
import { View, StyleSheet, FlatList } from 'react-native';
import { Text, Card, Title, Paragraph, FAB } from 'react-native-paper';
const NotesScreen: React.FC = () => {
const [notes] = React.useState([
{
id: '1',
title: 'Mobile App Architecture',
content: 'React Native with TypeScript, navigation, offline support...',
tags: ['architecture', 'mobile', 'react-native'],
createdAt: new Date(),
},
{
id: '2',
title: 'Meeting Notes - Product Review',
content: 'Discussed new features, timeline, and user feedback...',
tags: ['meeting', 'product', 'review'],
createdAt: new Date(),
},
]);
const renderNote = ({ item }: any) => (
<Card style={styles.card}>
<Card.Content>
<Title numberOfLines={1}>{item.title}</Title>
<Paragraph numberOfLines={3}>{item.content}</Paragraph>
<View style={styles.tagsContainer}>
{item.tags.map((tag: string, index: number) => (
<Text key={index} style={styles.tag}>
#{tag}
</Text>
))}
</View>
<Text style={styles.date}>
{item.createdAt.toLocaleDateString()}
</Text>
</Card.Content>
</Card>
);
return (
<View style={styles.container}>
<FlatList
data={notes}
renderItem={renderNote}
keyExtractor={(item) => item.id}
contentContainerStyle={styles.list}
showsVerticalScrollIndicator={false}
/>
<FAB
icon="plus"
style={styles.fab}
onPress={() => console.log('Add note')}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
list: {
padding: 16,
paddingBottom: 80,
},
card: {
marginBottom: 12,
elevation: 2,
},
tagsContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
marginTop: 8,
},
tag: {
backgroundColor: '#e8f5e8',
color: '#2e7d32',
paddingHorizontal: 8,
paddingVertical: 4,
borderRadius: 12,
fontSize: 10,
marginRight: 4,
marginBottom: 4,
},
date: {
fontSize: 10,
color: '#666',
marginTop: 8,
textAlign: 'right',
},
fab: {
position: 'absolute',
margin: 16,
right: 0,
bottom: 0,
backgroundColor: '#6200ee',
},
});
export default NotesScreen;
@@ -1,213 +0,0 @@
import React, { useState } from 'react';
import { View, StyleSheet, FlatList } from 'react-native';
import { Text, Card, Title, Paragraph, Searchbar, Chip } from 'react-native-paper';
const SearchScreen: React.FC = () => {
const [searchQuery, setSearchQuery] = useState('');
const [selectedFilter, setSelectedFilter] = useState('all');
const filters = [
{ id: 'all', label: 'All' },
{ id: 'bookmarks', label: 'Bookmarks' },
{ id: 'tasks', label: 'Tasks' },
{ id: 'notes', label: 'Notes' },
];
const searchResults = [
{
id: '1',
type: 'bookmark',
title: 'React Native Documentation',
description: 'Official React Native documentation and guides',
url: 'https://reactnative.dev',
},
{
id: '2',
type: 'task',
title: 'Complete mobile app setup',
description: 'Finish React Native project structure and navigation',
status: 'in_progress',
},
{
id: '3',
type: 'note',
title: 'Mobile App Architecture',
content: 'React Native with TypeScript, navigation patterns...',
tags: ['architecture', 'mobile'],
},
];
const onChangeSearch = (query: string) => setSearchQuery(query);
const renderResult = ({ item }: any) => {
const getTypeIcon = (type: string) => {
switch (type) {
case 'bookmark': return '🔖';
case 'task': return '✅';
case 'note': return '📝';
default: return '📄';
}
};
const getTypeColor = (type: string) => {
switch (type) {
case 'bookmark': return '#1976d2';
case 'task': return '#f44336';
case 'note': return '#4caf50';
default: return '#666';
}
};
return (
<Card style={styles.resultCard}>
<Card.Content>
<View style={styles.resultHeader}>
<Text style={styles.typeIcon}>{getTypeIcon(item.type)}</Text>
<Text style={[styles.typeLabel, { color: getTypeColor(item.type) }]}>
{item.type.charAt(0).toUpperCase() + item.type.slice(1)}
</Text>
</View>
<Title numberOfLines={1} style={styles.resultTitle}>
{item.title}
</Title>
<Paragraph numberOfLines={2} style={styles.resultDescription}>
{item.description || item.content}
</Paragraph>
{item.url && (
<Text style={styles.resultUrl} numberOfLines={1}>
{item.url}
</Text>
)}
{item.tags && (
<View style={styles.tagsContainer}>
{item.tags.map((tag: string, index: number) => (
<Chip key={index} style={styles.tag}>
{tag}
</Chip>
))}
</View>
)}
</Card.Content>
</Card>
);
};
return (
<View style={styles.container}>
<Searchbar
placeholder="Search everything..."
onChangeText={onChangeSearch}
value={searchQuery}
style={styles.searchBar}
/>
<View style={styles.filtersContainer}>
{filters.map(filter => (
<Chip
key={filter.id}
selected={selectedFilter === filter.id}
onPress={() => setSelectedFilter(filter.id)}
style={styles.filterChip}
>
{filter.label}
</Chip>
))}
</View>
<FlatList
data={searchResults}
renderItem={renderResult}
keyExtractor={(item) => item.id}
contentContainerStyle={styles.resultsList}
showsVerticalScrollIndicator={false}
ListEmptyComponent={
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}>
{searchQuery ? 'No results found' : 'Start typing to search'}
</Text>
</View>
}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
searchBar: {
margin: 16,
marginBottom: 8,
},
filtersContainer: {
flexDirection: 'row',
paddingHorizontal: 16,
paddingBottom: 8,
},
filterChip: {
marginRight: 8,
},
resultsList: {
paddingHorizontal: 16,
paddingBottom: 16,
},
resultCard: {
marginBottom: 12,
elevation: 2,
},
resultHeader: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 8,
},
typeIcon: {
fontSize: 16,
marginRight: 8,
},
typeLabel: {
fontSize: 12,
fontWeight: 'bold',
textTransform: 'uppercase',
},
resultTitle: {
fontSize: 16,
marginBottom: 4,
},
resultDescription: {
fontSize: 14,
color: '#666',
marginBottom: 8,
},
resultUrl: {
fontSize: 12,
color: '#1976d2',
marginBottom: 8,
},
tagsContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
},
tag: {
marginRight: 4,
marginBottom: 4,
},
emptyContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingVertical: 60,
},
emptyText: {
fontSize: 16,
color: '#666',
textAlign: 'center',
},
});
export default SearchScreen;
@@ -1,321 +0,0 @@
import React, { useState } from 'react';
import {
View,
StyleSheet,
KeyboardAvoidingView,
Platform,
Alert,
} from 'react-native';
import {
Card,
Title,
Paragraph,
TextInput,
Button,
HelperText,
} from 'react-native-paper';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useServerConfig } from '../services/ServerConfigContext';
import { updateAPIBaseURL } from '../services/api';
interface ServerConfig {
baseUrl: string;
username: string;
password: string;
}
const ServerSetupScreen: React.FC = () => {
const [config, setConfig] = useState<ServerConfig>({
baseUrl: '',
username: '',
password: '',
});
const [isLoading, setIsLoading] = useState(false);
const [errors, setErrors] = useState<Partial<ServerConfig>>({});
const { setConfig: saveConfig } = useServerConfig();
const validateConfig = (): boolean => {
const newErrors: Partial<ServerConfig> = {};
if (!config.baseUrl.trim()) {
newErrors.baseUrl = 'Server URL is required';
} else if (!isValidUrl(config.baseUrl)) {
newErrors.baseUrl = 'Please enter a valid URL (e.g., https://your-server.com)';
}
if (!config.username.trim()) {
newErrors.username = 'Username is required';
}
if (!config.password.trim()) {
newErrors.password = 'Password is required';
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const isValidUrl = (url: string): boolean => {
try {
const urlObj = new URL(url.startsWith('http') ? url : `https://${url}`);
return urlObj.protocol === 'http:' || urlObj.protocol === 'https:';
} catch {
return false;
}
};
const testConnection = async (): Promise<boolean> => {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10000);
const response = await fetch(`${config.baseUrl}/api/health`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
signal: controller.signal,
});
clearTimeout(timeoutId);
return response.ok;
} catch (error) {
console.error('Connection test failed:', error);
return false;
}
};
const handleTestConnection = async () => {
if (!config.baseUrl.trim()) {
Alert.alert('Error', 'Please enter a server URL first');
return;
}
setIsLoading(true);
try {
const isConnected = await testConnection();
if (isConnected) {
Alert.alert('Success', 'Connection to server successful!');
} else {
Alert.alert(
'Connection Failed',
'Could not connect to the server. Please check the URL and ensure the server is running.'
);
}
} catch (error) {
Alert.alert('Error', 'Failed to test connection. Please try again.');
} finally {
setIsLoading(false);
}
};
const handleSetup = async () => {
if (!validateConfig()) {
return;
}
setIsLoading(true);
try {
const isConnected = await testConnection();
if (!isConnected) {
Alert.alert(
'Connection Failed',
'Could not connect to the server. Please check the URL and try again.'
);
return;
}
// Test authentication
const authResponse = await fetch(`${config.baseUrl}/api/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: config.username,
password: config.password,
}),
});
if (authResponse.ok) {
const authData = await authResponse.json();
if (authData.token) {
await saveConfig(config);
updateAPIBaseURL(`${config.baseUrl}/api`);
Alert.alert('Success', 'Server configuration completed successfully!');
// Navigation will be handled automatically by the AppNavigator
} else {
Alert.alert('Authentication Failed', 'Invalid username or password.');
}
} else {
Alert.alert('Authentication Failed', 'Invalid username or password.');
}
} catch (error) {
Alert.alert('Setup Failed', 'An error occurred during setup. Please try again.');
} finally {
setIsLoading(false);
}
};
return (
<SafeAreaView style={styles.container}>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.keyboardAvoidingView}
>
<View style={styles.content}>
<Card style={styles.card}>
<Card.Content>
<Title style={styles.title}>Welcome to Trackeep</Title>
<Paragraph style={styles.subtitle}>
Connect to your Trackeep server to get started
</Paragraph>
</Card.Content>
</Card>
<Card style={styles.card}>
<Card.Content>
<Title style={styles.cardTitle}>Server Configuration</Title>
<TextInput
label="Server URL"
value={config.baseUrl}
onChangeText={(text) => setConfig({ ...config, baseUrl: text })}
placeholder="https://your-server.com"
autoCapitalize="none"
keyboardType="url"
style={styles.input}
error={!!errors.baseUrl}
/>
<HelperText type="error" visible={!!errors.baseUrl}>
{errors.baseUrl}
</HelperText>
<TextInput
label="Username"
value={config.username}
onChangeText={(text) => setConfig({ ...config, username: text })}
autoCapitalize="none"
autoCorrect={false}
style={styles.input}
error={!!errors.username}
/>
<HelperText type="error" visible={!!errors.username}>
{errors.username}
</HelperText>
<TextInput
label="Password"
value={config.password}
onChangeText={(text) => setConfig({ ...config, password: text })}
secureTextEntry
autoCapitalize="none"
autoCorrect={false}
style={styles.input}
error={!!errors.password}
/>
<HelperText type="error" visible={!!errors.password}>
{errors.password}
</HelperText>
<Button
mode="outlined"
onPress={handleTestConnection}
disabled={isLoading || !config.baseUrl.trim()}
style={styles.testButton}
loading={isLoading}
>
Test Connection
</Button>
</Card.Content>
</Card>
<Card style={styles.infoCard}>
<Card.Content>
<Title style={styles.cardTitle}>Need Help?</Title>
<Paragraph style={styles.infoText}>
Enter the full URL of your Trackeep server
</Paragraph>
<Paragraph style={styles.infoText}>
Use your existing Trackeep account credentials
</Paragraph>
<Paragraph style={styles.infoText}>
Make sure your server is accessible from this device
</Paragraph>
</Card.Content>
</Card>
<Button
mode="contained"
onPress={handleSetup}
disabled={isLoading}
loading={isLoading}
style={styles.setupButton}
contentStyle={styles.setupButtonContent}
>
Complete Setup
</Button>
</View>
</KeyboardAvoidingView>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
keyboardAvoidingView: {
flex: 1,
},
content: {
flex: 1,
padding: 16,
justifyContent: 'center',
},
card: {
marginBottom: 16,
elevation: 2,
},
infoCard: {
marginBottom: 24,
backgroundColor: '#e3f2fd',
},
title: {
textAlign: 'center',
fontSize: 24,
fontWeight: 'bold',
color: '#6200ee',
},
subtitle: {
textAlign: 'center',
marginTop: 8,
color: '#666',
},
cardTitle: {
fontSize: 18,
marginBottom: 16,
color: '#333',
},
input: {
marginBottom: 8,
},
testButton: {
marginTop: 8,
},
infoText: {
fontSize: 14,
color: '#666',
marginBottom: 4,
},
setupButton: {
backgroundColor: '#6200ee',
},
setupButtonContent: {
paddingVertical: 8,
},
});
export default ServerSetupScreen;
@@ -1,324 +0,0 @@
import React from 'react';
import { View, StyleSheet, ScrollView, Alert } from 'react-native';
import { List, Switch, Text, Card, Title, Button } from 'react-native-paper';
import { useAuth } from '../services/AuthContext';
import { useOffline } from '../services/OfflineContext';
import { useNotifications } from '../services/NotificationContext';
import { useCamera } from '../services/CameraContext';
import { useVoice } from '../services/VoiceContext';
const SettingsScreen: React.FC = () => {
const { user, logout } = useAuth();
const { isOnline, syncNow } = useOffline();
const { hasPermission: hasNotificationPermission, requestPermission: requestNotificationPermission } = useNotifications();
const { hasPermission: hasCameraPermission, requestPermission: requestCameraPermission, scanDocument } = useCamera();
const { hasPermission: hasVoicePermission, requestPermission: requestVoicePermission, isRecording, startRecording, stopRecording } = useVoice();
const [notifications, setNotifications] = React.useState(true);
const [darkMode, setDarkMode] = React.useState(false);
const [autoSync, setAutoSync] = React.useState(true);
const handleLogout = async () => {
await logout();
};
const handleNotificationPermission = async () => {
if (!hasNotificationPermission) {
const granted = await requestNotificationPermission();
if (granted) {
Alert.alert('Success', 'Notification permission granted!');
} else {
Alert.alert('Permission Denied', 'Notification permission is required for reminders');
}
}
};
const handleCameraPermission = async () => {
if (!hasCameraPermission) {
const granted = await requestCameraPermission();
if (granted) {
Alert.alert('Success', 'Camera permission granted!');
} else {
Alert.alert('Permission Denied', 'Camera permission is required for document scanning');
}
}
};
const handleVoicePermission = async () => {
if (!hasVoicePermission) {
const granted = await requestVoicePermission();
if (granted) {
Alert.alert('Success', 'Microphone permission granted!');
} else {
Alert.alert('Permission Denied', 'Microphone permission is required for voice recording');
}
}
};
const handleTestNotification = () => {
// This would use the notification service to show a test notification
Alert.alert('Test Notification', 'This is a test notification!');
};
const handleTestCamera = async () => {
try {
const result = await scanDocument();
if (result) {
Alert.alert('Success', 'Document scanned successfully!');
}
} catch (error) {
Alert.alert('Error', 'Failed to scan document');
}
};
const handleTestVoice = async () => {
if (isRecording) {
const recording = await stopRecording();
if (recording) {
Alert.alert('Success', `Voice recorded! Duration: ${recording.duration}s`);
}
} else {
startRecording();
Alert.alert('Recording', 'Voice recording started...');
}
};
return (
<View style={styles.container}>
<ScrollView style={styles.scrollView}>
<Card style={styles.card}>
<Card.Content>
<Title>Account</Title>
<Text style={styles.userInfo}>
{user?.name} ({user?.email})
</Text>
<Button
mode="outlined"
onPress={handleLogout}
style={styles.logoutButton}
>
Sign Out
</Button>
</Card.Content>
</Card>
<Card style={styles.card}>
<Card.Content>
<Title>Preferences</Title>
<List.Item
title="Push Notifications"
description="Receive notifications for tasks and reminders"
right={() => (
<Switch
value={notifications}
onValueChange={setNotifications}
/>
)}
/>
<List.Item
title="Dark Mode"
description="Use dark theme"
right={() => (
<Switch
value={darkMode}
onValueChange={setDarkMode}
/>
)}
/>
<List.Item
title="Auto Sync"
description="Automatically sync when online"
right={() => (
<Switch
value={autoSync}
onValueChange={setAutoSync}
/>
)}
/>
</Card.Content>
</Card>
<Card style={styles.card}>
<Card.Content>
<Title>📱 Mobile Features</Title>
<List.Item
title="Push Notifications"
description={hasNotificationPermission ? "Permission granted" : "Permission required"}
left={() => <Text style={styles.featureIcon}>🔔</Text>}
right={() => (
<View style={styles.featureActions}>
{!hasNotificationPermission && (
<Button
mode="outlined"
onPress={handleNotificationPermission}
compact
>
Enable
</Button>
)}
{hasNotificationPermission && (
<Button
mode="text"
onPress={handleTestNotification}
compact
>
Test
</Button>
)}
</View>
)}
/>
<List.Item
title="Camera & Document Scanning"
description={hasCameraPermission ? "Permission granted" : "Permission required"}
left={() => <Text style={styles.featureIcon}>📸</Text>}
right={() => (
<View style={styles.featureActions}>
{!hasCameraPermission && (
<Button
mode="outlined"
onPress={handleCameraPermission}
compact
>
Enable
</Button>
)}
{hasCameraPermission && (
<Button
mode="text"
onPress={handleTestCamera}
compact
>
Test
</Button>
)}
</View>
)}
/>
<List.Item
title="Voice Recording"
description={hasVoicePermission ? "Permission granted" : "Permission required"}
left={() => <Text style={styles.featureIcon}>🎤</Text>}
right={() => (
<View style={styles.featureActions}>
{!hasVoicePermission && (
<Button
mode="outlined"
onPress={handleVoicePermission}
compact
>
Enable
</Button>
)}
{hasVoicePermission && (
<Button
mode={isRecording ? "contained" : "text"}
onPress={handleTestVoice}
compact
>
{isRecording ? "Stop" : "Test"}
</Button>
)}
</View>
)}
/>
</Card.Content>
</Card>
<Card style={styles.card}>
<Card.Content>
<Title>Sync Status</Title>
<List.Item
title="Connection"
description={isOnline ? 'Connected' : 'Offline'}
left={() => (
<Text style={styles.statusIcon}>
{isOnline ? '🟢' : '🔴'}
</Text>
)}
/>
<Button
mode="outlined"
onPress={syncNow}
disabled={!isOnline}
style={styles.syncButton}
>
Sync Now
</Button>
</Card.Content>
</Card>
<Card style={styles.card}>
<Card.Content>
<Title>About</Title>
<List.Item
title="Version"
description="1.0.0"
/>
<List.Item
title="Build"
description="React Native Mobile App"
/>
<List.Item
title="GitHub"
description="View source code"
onPress={() => console.log('Open GitHub')}
/>
</Card.Content>
</Card>
</ScrollView>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
scrollView: {
flex: 1,
},
card: {
margin: 16,
elevation: 2,
},
userInfo: {
fontSize: 16,
marginBottom: 16,
color: '#666',
},
logoutButton: {
marginTop: 8,
},
statusIcon: {
fontSize: 16,
width: 24,
textAlign: 'center',
},
syncButton: {
marginTop: 8,
},
featureIcon: {
fontSize: 16,
width: 24,
textAlign: 'center',
},
featureActions: {
flexDirection: 'row',
alignItems: 'center',
},
});
export default SettingsScreen;
@@ -1,132 +0,0 @@
import React from 'react';
import { View, StyleSheet, FlatList } from 'react-native';
import { Text, Card, Title, Paragraph, FAB, Checkbox } from 'react-native-paper';
const TasksScreen: React.FC = () => {
const [tasks, setTasks] = React.useState([
{
id: '1',
title: 'Complete mobile app setup',
description: 'Finish React Native project structure',
status: 'in_progress' as const,
priority: 'high' as const,
completed: false,
},
{
id: '2',
title: 'Review pull requests',
description: 'Check and merge pending PRs',
status: 'todo' as const,
priority: 'medium' as const,
completed: false,
},
]);
const toggleTask = (taskId: string) => {
setTasks(prev =>
prev.map(task =>
task.id === taskId ? { ...task, completed: !task.completed } : task
)
);
};
const getPriorityColor = (priority: string) => {
switch (priority) {
case 'high': return '#f44336';
case 'medium': return '#ff9800';
case 'low': return '#4caf50';
default: return '#666';
}
};
const renderTask = ({ item }: any) => (
<Card style={styles.card}>
<Card.Content>
<View style={styles.taskHeader}>
<Checkbox
status={item.completed ? 'checked' : 'unchecked'}
onPress={() => toggleTask(item.id)}
/>
<View style={styles.taskContent}>
<Title style={[styles.taskTitle, item.completed && styles.completedTitle]}>
{item.title}
</Title>
<Paragraph style={styles.taskDescription}>
{item.description}
</Paragraph>
<Text style={[styles.priority, { color: getPriorityColor(item.priority) }]}>
{item.priority.toUpperCase()}
</Text>
</View>
</View>
</Card.Content>
</Card>
);
return (
<View style={styles.container}>
<FlatList
data={tasks}
renderItem={renderTask}
keyExtractor={(item) => item.id}
contentContainerStyle={styles.list}
showsVerticalScrollIndicator={false}
/>
<FAB
icon="plus"
style={styles.fab}
onPress={() => console.log('Add task')}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
list: {
padding: 16,
paddingBottom: 80,
},
card: {
marginBottom: 12,
elevation: 2,
},
taskHeader: {
flexDirection: 'row',
alignItems: 'flex-start',
},
taskContent: {
flex: 1,
marginLeft: 12,
},
taskTitle: {
fontSize: 16,
},
completedTitle: {
textDecorationLine: 'line-through',
color: '#666',
},
taskDescription: {
marginTop: 4,
fontSize: 14,
},
priority: {
fontSize: 10,
fontWeight: 'bold',
marginTop: 8,
textTransform: 'uppercase',
},
fab: {
position: 'absolute',
margin: 16,
right: 0,
bottom: 0,
backgroundColor: '#6200ee',
},
});
export default TasksScreen;
@@ -1,194 +0,0 @@
import React, { useState, useEffect } from 'react';
import { View, StyleSheet } from 'react-native';
import { Text, Card, Title, Paragraph, Button, FAB } from 'react-native-paper';
const TimeTrackingScreen: React.FC = () => {
const [isTimerRunning, setIsTimerRunning] = useState(false);
const [elapsedTime, setElapsedTime] = useState(0);
const [currentTask, setCurrentTask] = useState('');
useEffect(() => {
let interval: NodeJS.Timeout;
if (isTimerRunning) {
interval = setInterval(() => {
setElapsedTime(prev => prev + 1);
}, 1000);
}
return () => clearInterval(interval);
}, [isTimerRunning]);
const formatTime = (seconds: number) => {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = seconds % 60;
return `${hours.toString().padStart(2, '0')}:${minutes
.toString()
.padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
};
const toggleTimer = () => {
setIsTimerRunning(!isTimerRunning);
};
const resetTimer = () => {
setIsTimerRunning(false);
setElapsedTime(0);
setCurrentTask('');
};
const timeEntries = [
{
id: '1',
description: 'Mobile app development',
duration: '2:30:00',
date: 'Today',
},
{
id: '2',
description: 'Code review',
duration: '0:45:00',
date: 'Yesterday',
},
];
return (
<View style={styles.container}>
<Card style={styles.timerCard}>
<Card.Content>
<Title style={styles.timerTitle}>Time Tracker</Title>
<Text style={styles.timeDisplay}>{formatTime(elapsedTime)}</Text>
{currentTask ? (
<Paragraph style={styles.currentTask}>
Working on: {currentTask}
</Paragraph>
) : (
<Paragraph style={styles.noTask}>
No task selected
</Paragraph>
)}
<View style={styles.timerButtons}>
<Button
mode={isTimerRunning ? 'outlined' : 'contained'}
onPress={toggleTimer}
style={styles.timerButton}
>
{isTimerRunning ? 'Pause' : 'Start'}
</Button>
<Button
mode="outlined"
onPress={resetTimer}
style={styles.timerButton}
>
Reset
</Button>
</View>
</Card.Content>
</Card>
<Card style={styles.entriesCard}>
<Card.Content>
<Title>Recent Entries</Title>
{timeEntries.map(entry => (
<View key={entry.id} style={styles.entryItem}>
<View style={styles.entryContent}>
<Text style={styles.entryDescription}>
{entry.description}
</Text>
<Text style={styles.entryDuration}>
{entry.duration}
</Text>
</View>
<Text style={styles.entryDate}>{entry.date}</Text>
</View>
))}
</Card.Content>
</Card>
<FAB
icon="plus"
style={styles.fab}
onPress={() => console.log('Add time entry')}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
padding: 16,
},
timerCard: {
marginBottom: 16,
elevation: 4,
},
timerTitle: {
textAlign: 'center',
marginBottom: 16,
},
timeDisplay: {
fontSize: 48,
fontWeight: 'bold',
textAlign: 'center',
color: '#6200ee',
marginBottom: 16,
},
currentTask: {
textAlign: 'center',
color: '#666',
marginBottom: 16,
},
noTask: {
textAlign: 'center',
color: '#999',
fontStyle: 'italic',
marginBottom: 16,
},
timerButtons: {
flexDirection: 'row',
justifyContent: 'space-around',
},
timerButton: {
flex: 1,
marginHorizontal: 8,
},
entriesCard: {
elevation: 2,
},
entryItem: {
paddingVertical: 12,
borderBottomWidth: 1,
borderBottomColor: '#eee',
},
entryContent: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
entryDescription: {
flex: 1,
fontSize: 16,
},
entryDuration: {
fontSize: 16,
fontWeight: 'bold',
color: '#6200ee',
},
entryDate: {
fontSize: 12,
color: '#666',
marginTop: 4,
},
fab: {
position: 'absolute',
margin: 16,
right: 0,
bottom: 0,
backgroundColor: '#6200ee',
},
});
export default TimeTrackingScreen;

Some files were not shown because too many files have changed in this diff Show More