From 3c1209a5a9a86bd478f0247d7b587aee4a489b33 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 16 Jun 2025 21:50:44 +0300 Subject: [PATCH] Express migration (#80) * Initial migration * Cleanup and create migration scripts * Introduce test suite * Fix test issues * Correct CORS issue and update paths * Update README --- .babelrc | 8 - .dockerignore | 116 +- .gitignore | 2 + .rubocop.yml | 8 - Dockerfile | 232 +- Gemfile | 28 - Gemfile.lock | 146 - README.md | 181 +- Rakefile | 12 - app.rb | 208 - app/config/database.yml | 17 - app/config/puma.rb | 9 - app/helpers/authentication_helper.rb | 21 - app/models/area.rb | 6 - app/models/inbox_item.rb | 22 - app/models/note.rb | 8 - app/models/project.rb | 39 - app/models/tag.rb | 8 - app/models/task.rb | 178 - app/models/user.rb | 20 - app/routes/areas_routes.rb | 74 - app/routes/authentication_routes.rb | 49 - app/routes/inbox_routes.rb | 92 - app/routes/notes_routes.rb | 134 - app/routes/projects_routes.rb | 136 - app/routes/tags_routes.rb | 67 - app/routes/tasks_routes.rb | 159 - app/routes/telegram_poller.rb | 231 - app/routes/telegram_routes.rb | 160 - app/routes/url_routes.rb | 43 - app/routes/users_routes.rb | 168 - app/services/task_summary_service.rb | 288 - app/services/url_title_extractor_service.rb | 71 - app/views/index.erb | 12 - app/views/layout.erb | 12 - backend/.env.test | 4 + backend/.sequelizerc | 8 + backend/app.js | 167 + backend/config/database.js | 42 + {config => backend/config}/quotes.yml | 0 backend/jest.config.js | 25 + backend/middleware/auth.js | 30 + .../migrations/20250615000001-create-users.js | 61 + backend/models/area.js | 36 + backend/models/inbox_item.js | 42 + backend/models/index.js | 93 + backend/models/note.js | 47 + backend/models/project.js | 69 + backend/models/tag.js | 32 + backend/models/task.js | 127 + backend/models/user.js | 100 + backend/package-lock.json | 8045 +++++++++++++++++ backend/package.json | 52 + backend/routes/areas.js | 130 + backend/routes/auth.js | 78 + backend/routes/inbox.js | 157 + backend/routes/notes.js | 242 + backend/routes/projects.js | 275 + backend/routes/quotes.js | 30 + backend/routes/tags.js | 132 + backend/routes/tasks.js | 394 + backend/routes/telegram.js | 113 + backend/routes/url.js | 156 + backend/routes/users.js | 206 + backend/scripts/db-init.js | 27 + backend/scripts/db-migrate.js | 27 + backend/scripts/db-reset.js | 27 + backend/scripts/db-status.js | 69 + backend/scripts/db-sync.js | 26 + backend/scripts/migration-create.js | 108 + backend/scripts/user-create.js | 66 + backend/services/quotesService.js | 65 + backend/services/taskScheduler.js | 181 + backend/services/taskSummaryService.js | 238 + backend/services/telegramInitializer.js | 43 + backend/services/telegramPoller.js | 261 + backend/start.sh | 11 + backend/tests/README.md | 82 + backend/tests/helpers/setup.js | 39 + backend/tests/helpers/testUtils.js | 28 + backend/tests/integration/areas.test.js | 280 + backend/tests/integration/auth.test.js | 155 + backend/tests/integration/inbox.test.js | 275 + backend/tests/integration/notes.test.js | 308 + backend/tests/integration/projects.test.js | 303 + backend/tests/integration/quotes.test.js | 168 + backend/tests/integration/tags.test.js | 270 + backend/tests/integration/tasks.test.js | 274 + backend/tests/integration/telegram.test.js | 152 + backend/tests/integration/url.test.js | 178 + backend/tests/integration/users.test.js | 283 + backend/tests/unit/middleware/auth.test.js | 130 + backend/tests/unit/models/area.test.js | 74 + backend/tests/unit/models/inbox_item.test.js | 96 + backend/tests/unit/models/note.test.js | 102 + backend/tests/unit/models/project.test.js | 141 + backend/tests/unit/models/tag.test.js | 83 + backend/tests/unit/models/task.test.js | 183 + backend/tests/unit/models/user.test.js | 135 + config.ru | 2 - config/initializers/scheduler.rb | 184 - config/initializers/telegram_initializer.rb | 51 - console.rb | 4 - cookies.txt | 5 - create_migration.sh | 3 - db/migrate/20231107102451_create_users.rb | 11 - db/migrate/20231107102516_create_areas.rb | 10 - db/migrate/20231107102609_create_projects.rb | 11 - db/migrate/20231107102631_create_tasks.rb | 13 - .../20231109055429_add_fields_to_tasks.rb | 7 - .../20231109055533_add_fields_to_projects.rb | 5 - ...dd_cascade_delete_to_projects_and_tasks.rb | 9 - db/migrate/20231114203847_add_tags.rb | 10 - .../20231114210336_create_tasks_tags.rb | 8 - ...5092055_rename_tasks_tags_to_tags_tasks.rb | 5 - db/migrate/20231116112552_create_notes.rb | 10 - ...1116120633_create_join_table_notes_tags.rb | 8 - .../20231117170940_add_title_to_notes.rb | 5 - .../20231117174412_add_project_to_notes.rb | 5 - ...20231127092131_change_priority_in_tasks.rb | 33 - ...1127094906_add_note_and_status_to_tasks.rb | 27 - .../20240326093339_add_active_to_projects.rb | 5 - ...06225631_add_pin_to_sidebar_to_projects.rb | 5 - ...41007143928_add_profile_fields_to_users.rb | 8 - ...41016105827_create_description_for_area.rb | 5 - .../20241121113756_create_projects_tags.rb | 14 - ...20241126095028_add_priority_to_projects.rb | 5 - ...50224162915_add_due_date_at_to_projects.rb | 5 - .../20250414134722_create_inbox_items.rb | 11 - ...50414150330_add_telegram_token_to_users.rb | 6 - ...0250416231240_add_task_summary_to_users.rb | 7 - ..._add_task_summary_run_tracking_to_users.rb | 7 - db/schema.rb | 141 - db/seeds.rb | 39 - ...mponents_Tasks_tsx.bcee0af8633c28243d32.js | 92 - dist/index.html | 12 - dist/main.5904574f25ca7c8b87ba.js | 5392 ----------- ...rowser-ponyfill_js.6451a0808e985bae004f.js | 21 - frontend/__tests__/components/Login.test.tsx | 96 + frontend/__tests__/components/Navbar.test.tsx | 286 + .../__tests__/components/Projects.test.tsx | 165 + .../__tests__/components/TaskItem.test.tsx | 52 + .../__tests__/components/TaskList.test.tsx | 176 + .../__tests__/components/TaskModal.test.tsx | 289 + .../integration/taskWorkflows.test.tsx | 413 + frontend/__tests__/setup.ts | 65 + frontend/__tests__/store/useStore.test.ts | 130 + frontend/__tests__/utils/authUtils.test.ts | 310 + frontend/__tests__/utils/dateUtils.test.ts | 108 + frontend/__tests__/utils/tasksService.test.ts | 172 + jest.config.js | 28 + package-lock.json | 6340 ++++++++++++- package.json | 13 +- ...pp_frontend_components_Tasks_tsx.bundle.js | 92 - ...app_frontend_utils_urlService_ts.bundle.js | 22 - .../frontend_components_Tasks_tsx.bundle.js | 92 - ...s-fetch_dist_browser-ponyfill_js.bundle.js | 21 - public/locales/en/translation.json | 35 +- public/locales/es/translation.json | 179 +- public/translation-test.html | 79 - run.sh | 39 - .../components/Inbox/InboxItemDetail.tsx | 0 test-i18n.html | 48 - test.js | 1 - test/test_app.rb | 28 - translation.json | 92 - webpack.config.js | 2 +- 167 files changed, 24985 insertions(+), 9335 deletions(-) delete mode 100644 .babelrc delete mode 100644 .rubocop.yml delete mode 100644 Gemfile delete mode 100644 Gemfile.lock delete mode 100644 Rakefile delete mode 100644 app.rb delete mode 100644 app/config/database.yml delete mode 100644 app/config/puma.rb delete mode 100644 app/helpers/authentication_helper.rb delete mode 100644 app/models/area.rb delete mode 100644 app/models/inbox_item.rb delete mode 100644 app/models/note.rb delete mode 100644 app/models/project.rb delete mode 100644 app/models/tag.rb delete mode 100644 app/models/task.rb delete mode 100644 app/models/user.rb delete mode 100644 app/routes/areas_routes.rb delete mode 100644 app/routes/authentication_routes.rb delete mode 100644 app/routes/inbox_routes.rb delete mode 100644 app/routes/notes_routes.rb delete mode 100644 app/routes/projects_routes.rb delete mode 100644 app/routes/tags_routes.rb delete mode 100644 app/routes/tasks_routes.rb delete mode 100644 app/routes/telegram_poller.rb delete mode 100644 app/routes/telegram_routes.rb delete mode 100644 app/routes/url_routes.rb delete mode 100644 app/routes/users_routes.rb delete mode 100644 app/services/task_summary_service.rb delete mode 100644 app/services/url_title_extractor_service.rb delete mode 100644 app/views/index.erb delete mode 100644 app/views/layout.erb create mode 100644 backend/.env.test create mode 100644 backend/.sequelizerc create mode 100644 backend/app.js create mode 100644 backend/config/database.js rename {config => backend/config}/quotes.yml (100%) create mode 100644 backend/jest.config.js create mode 100644 backend/middleware/auth.js create mode 100644 backend/migrations/20250615000001-create-users.js create mode 100644 backend/models/area.js create mode 100644 backend/models/inbox_item.js create mode 100644 backend/models/index.js create mode 100644 backend/models/note.js create mode 100644 backend/models/project.js create mode 100644 backend/models/tag.js create mode 100644 backend/models/task.js create mode 100644 backend/models/user.js create mode 100644 backend/package-lock.json create mode 100644 backend/package.json create mode 100644 backend/routes/areas.js create mode 100644 backend/routes/auth.js create mode 100644 backend/routes/inbox.js create mode 100644 backend/routes/notes.js create mode 100644 backend/routes/projects.js create mode 100644 backend/routes/quotes.js create mode 100644 backend/routes/tags.js create mode 100644 backend/routes/tasks.js create mode 100644 backend/routes/telegram.js create mode 100644 backend/routes/url.js create mode 100644 backend/routes/users.js create mode 100755 backend/scripts/db-init.js create mode 100755 backend/scripts/db-migrate.js create mode 100755 backend/scripts/db-reset.js create mode 100755 backend/scripts/db-status.js create mode 100755 backend/scripts/db-sync.js create mode 100755 backend/scripts/migration-create.js create mode 100755 backend/scripts/user-create.js create mode 100644 backend/services/quotesService.js create mode 100644 backend/services/taskScheduler.js create mode 100644 backend/services/taskSummaryService.js create mode 100644 backend/services/telegramInitializer.js create mode 100644 backend/services/telegramPoller.js create mode 100755 backend/start.sh create mode 100644 backend/tests/README.md create mode 100644 backend/tests/helpers/setup.js create mode 100644 backend/tests/helpers/testUtils.js create mode 100644 backend/tests/integration/areas.test.js create mode 100644 backend/tests/integration/auth.test.js create mode 100644 backend/tests/integration/inbox.test.js create mode 100644 backend/tests/integration/notes.test.js create mode 100644 backend/tests/integration/projects.test.js create mode 100644 backend/tests/integration/quotes.test.js create mode 100644 backend/tests/integration/tags.test.js create mode 100644 backend/tests/integration/tasks.test.js create mode 100644 backend/tests/integration/telegram.test.js create mode 100644 backend/tests/integration/url.test.js create mode 100644 backend/tests/integration/users.test.js create mode 100644 backend/tests/unit/middleware/auth.test.js create mode 100644 backend/tests/unit/models/area.test.js create mode 100644 backend/tests/unit/models/inbox_item.test.js create mode 100644 backend/tests/unit/models/note.test.js create mode 100644 backend/tests/unit/models/project.test.js create mode 100644 backend/tests/unit/models/tag.test.js create mode 100644 backend/tests/unit/models/task.test.js create mode 100644 backend/tests/unit/models/user.test.js delete mode 100644 config.ru delete mode 100644 config/initializers/scheduler.rb delete mode 100644 config/initializers/telegram_initializer.rb delete mode 100644 console.rb delete mode 100644 cookies.txt delete mode 100755 create_migration.sh delete mode 100644 db/migrate/20231107102451_create_users.rb delete mode 100644 db/migrate/20231107102516_create_areas.rb delete mode 100644 db/migrate/20231107102609_create_projects.rb delete mode 100644 db/migrate/20231107102631_create_tasks.rb delete mode 100644 db/migrate/20231109055429_add_fields_to_tasks.rb delete mode 100644 db/migrate/20231109055533_add_fields_to_projects.rb delete mode 100644 db/migrate/20231110163101_add_cascade_delete_to_projects_and_tasks.rb delete mode 100644 db/migrate/20231114203847_add_tags.rb delete mode 100644 db/migrate/20231114210336_create_tasks_tags.rb delete mode 100644 db/migrate/20231115092055_rename_tasks_tags_to_tags_tasks.rb delete mode 100644 db/migrate/20231116112552_create_notes.rb delete mode 100644 db/migrate/20231116120633_create_join_table_notes_tags.rb delete mode 100644 db/migrate/20231117170940_add_title_to_notes.rb delete mode 100644 db/migrate/20231117174412_add_project_to_notes.rb delete mode 100644 db/migrate/20231127092131_change_priority_in_tasks.rb delete mode 100644 db/migrate/20231127094906_add_note_and_status_to_tasks.rb delete mode 100644 db/migrate/20240326093339_add_active_to_projects.rb delete mode 100644 db/migrate/20241006225631_add_pin_to_sidebar_to_projects.rb delete mode 100644 db/migrate/20241007143928_add_profile_fields_to_users.rb delete mode 100644 db/migrate/20241016105827_create_description_for_area.rb delete mode 100644 db/migrate/20241121113756_create_projects_tags.rb delete mode 100644 db/migrate/20241126095028_add_priority_to_projects.rb delete mode 100644 db/migrate/20250224162915_add_due_date_at_to_projects.rb delete mode 100644 db/migrate/20250414134722_create_inbox_items.rb delete mode 100644 db/migrate/20250414150330_add_telegram_token_to_users.rb delete mode 100644 db/migrate/20250416231240_add_task_summary_to_users.rb delete mode 100644 db/migrate/20250416235420_add_task_summary_run_tracking_to_users.rb delete mode 100644 db/schema.rb delete mode 100644 db/seeds.rb delete mode 100644 dist/frontend_components_Tasks_tsx.bcee0af8633c28243d32.js delete mode 100644 dist/index.html delete mode 100644 dist/main.5904574f25ca7c8b87ba.js delete mode 100644 dist/vendors-node_modules_cross-fetch_dist_browser-ponyfill_js.6451a0808e985bae004f.js create mode 100644 frontend/__tests__/components/Login.test.tsx create mode 100644 frontend/__tests__/components/Navbar.test.tsx create mode 100644 frontend/__tests__/components/Projects.test.tsx create mode 100644 frontend/__tests__/components/TaskItem.test.tsx create mode 100644 frontend/__tests__/components/TaskList.test.tsx create mode 100644 frontend/__tests__/components/TaskModal.test.tsx create mode 100644 frontend/__tests__/integration/taskWorkflows.test.tsx create mode 100644 frontend/__tests__/setup.ts create mode 100644 frontend/__tests__/store/useStore.test.ts create mode 100644 frontend/__tests__/utils/authUtils.test.ts create mode 100644 frontend/__tests__/utils/dateUtils.test.ts create mode 100644 frontend/__tests__/utils/tasksService.test.ts create mode 100644 jest.config.js delete mode 100644 public/js/app_frontend_components_Tasks_tsx.bundle.js delete mode 100644 public/js/app_frontend_utils_urlService_ts.bundle.js delete mode 100644 public/js/frontend_components_Tasks_tsx.bundle.js delete mode 100644 public/js/vendors-node_modules_cross-fetch_dist_browser-ponyfill_js.bundle.js delete mode 100644 public/translation-test.html delete mode 100755 run.sh delete mode 100644 src/app/frontend/components/Inbox/InboxItemDetail.tsx delete mode 100644 test-i18n.html delete mode 100644 test.js delete mode 100644 test/test_app.rb delete mode 100644 translation.json diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 292c70c..0000000 --- a/.babelrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "presets": [ - "@babel/preset-env", - "@babel/preset-react", - "@babel/preset-typescript" - ], - "plugins": ["react-refresh/babel"] -} diff --git a/.dockerignore b/.dockerignore index 06067e9..0acd217 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,110 @@ -db/*.sqlite3 -*.sqlite3 -*.sqlite3-shm -*.sqlite3-wal -certs/ -.DS_Store \ No newline at end of file +# ============================================================================ +# Optimized .dockerignore for multi-stage build +# ============================================================================ + +# Node modules (installed in container) +**/node_modules/ +**/.npm + +# Development files +*.log +*.tmp +*.swp +*.swo +*~ +**/.env.local +**/.env.development +**/.env.test + +# Git and version control +.git/ +.gitignore +.gitattributes +.github/ + +# Development databases +**/db/*.sqlite3* +**/*.sqlite3* +**/db/*.db + +# IDE and editor files +.vscode/ +.idea/ +*.sublime-* +**/.editorconfig + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Test files +test/ +spec/ +**/*.test.js +**/*.spec.js +**/jest.config.* +**/vitest.config.* + +# Documentation and assets +README.md +LICENSE +docs/ +screenshots/ +**/*.md + +# Build artifacts (built in container) +dist/ +build/ +.next/ +.nuxt/ +coverage/ +.nyc_output/ + +# Temporary and cache files +tmp/ +temp/ +.cache/ +**/.cache +**/npm-debug.log* +**/yarn-debug.log* +**/yarn-error.log* + +# Development only +frontend.log +server.log +cookies.txt +**/.eslintcache + +# Certificates (generated in container) +**/certs/ + +# Docker related (avoid recursion) +Dockerfile* +docker-compose*.yml +.dockerignore + +# Development scripts not needed in production +backend-express/scripts/ +backend-express/migrations/ +backend-express/seeders/ + +# Additional exclusions for minimal image +backend-express/test/ +backend-express/tests/ +**/node_modules/.cache/ +**/.git/ +**/.gitignore +**/yarn.lock +**/*.log +**/*.tmp +**/coverage/ + +# Backup files +**/*.bak +**/*.backup +**/*.orig \ No newline at end of file diff --git a/.gitignore b/.gitignore index 816b011..9ba04af 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ node_modules public/js/bundle.js .aider* + +backend/coverage/ \ No newline at end of file diff --git a/.rubocop.yml b/.rubocop.yml deleted file mode 100644 index 18f1d6a..0000000 --- a/.rubocop.yml +++ /dev/null @@ -1,8 +0,0 @@ -Metrics/ClassLength: - Max: 500 -Metrics/BlockLength: - Max: 50 -Metrics/MethodLength: - Max: 50 -Style/Documentation: - Enabled: false diff --git a/Dockerfile b/Dockerfile index eb02f4f..a3fb0cf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,108 +1,156 @@ -# Use a base image that supports both Node.js and Ruby -FROM ruby:3.2.2-slim +# ============================================================================ +# Ultra-optimized multi-stage build for minimal rootless Docker image +# ============================================================================ -# Install Node.js and necessary packages -RUN apt-get update -qq && \ - apt-get install -y --no-install-recommends \ - build-essential \ - libsqlite3-dev \ - openssl \ - libffi-dev \ - libpq-dev \ - curl \ - gnupg2 \ - ca-certificates && \ - # Install Node.js 20 - curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \ - apt-get install -y nodejs && \ - rm -rf /var/lib/apt/lists/* && \ - apt-get clean +# Stage 1: Frontend Build Environment (optimized) +FROM node:20-alpine AS frontend-builder -WORKDIR /usr/src/app +WORKDIR /app -# Install Ruby dependencies first -COPY Gemfile* ./ -RUN bundle config set --local deployment 'true' && \ - bundle config set --local without 'development test' && \ - bundle install --jobs 4 --retry 3 - -# Install Node.js dependencies +# Copy frontend package files COPY package*.json ./ -COPY webpack.config.js ./ -COPY babel.config.js ./ -COPY tsconfig.json ./ -COPY postcss.config.js ./ -COPY tailwind.config.js ./ -RUN npm ci +COPY webpack.config.js babel.config.js tsconfig.json postcss.config.js tailwind.config.js ./ -# Remove any existing development databases -RUN rm -f db/development* +# Install frontend dependencies (including dev deps for build) +RUN npm install --ignore-scripts --no-audit --no-fund && \ + npm cache clean --force && \ + rm -rf ~/.npm -# Copy application files -COPY app/ app/ -COPY config/ config/ -COPY config.ru ./ -COPY Rakefile ./ -COPY app.rb ./ -COPY db/migrate/ db/migrate/ -COPY db/schema.rb db/schema.rb +# Copy frontend source code COPY frontend/ frontend/ COPY public/ public/ -COPY src/ src/ -# Create non-root user for security -RUN useradd -m -U app && \ - chown -R app:app /usr/src/app +# Build frontend assets with optimizations +RUN NODE_ENV=production npm run build && \ + # Remove source maps and dev artifacts + find dist -name "*.map" -delete && \ + find dist -name "*.dev.*" -delete && \ + # Compress built assets + find dist -type f \( -name "*.js" -o -name "*.css" -o -name "*.html" \) -exec gzip -9 -k {} \; +# Stage 2: Backend Dependencies (ultra-minimal) +FROM node:20-alpine AS backend-deps + +WORKDIR /app + +# Install build dependencies temporarily for native modules +RUN apk add --no-cache --virtual .build-deps \ + python3 \ + make \ + g++ \ + sqlite-dev + +# Install only runtime dependencies for backend +COPY backend/package*.json ./ +RUN npm install --production --no-audit --no-fund && \ + npm cache clean --force && \ + rm -rf ~/.npm /tmp/* && \ + # Remove build dependencies after install + apk del .build-deps && \ + # Remove unnecessary files from node_modules + find node_modules -name "*.md" -delete && \ + find node_modules -name "*.txt" -delete && \ + find node_modules -name "LICENSE*" -delete && \ + find node_modules -name "CHANGELOG*" -delete && \ + find node_modules -name "README*" -delete && \ + find node_modules -name ".github" -type d -exec rm -rf {} + 2>/dev/null || true && \ + find node_modules -name "test" -type d -exec rm -rf {} + 2>/dev/null || true && \ + find node_modules -name "tests" -type d -exec rm -rf {} + 2>/dev/null || true && \ + find node_modules -name "docs" -type d -exec rm -rf {} + 2>/dev/null || true && \ + find node_modules -name "examples" -type d -exec rm -rf {} + 2>/dev/null || true + +# Stage 3: Test Stage (run tests before production) +FROM node:20-alpine AS test + +WORKDIR /app + +# Install build dependencies for testing +RUN apk add --no-cache --virtual .test-deps \ + python3 \ + make \ + g++ \ + sqlite-dev + +# Copy backend package files and install all dependencies (including dev) +COPY backend/package*.json ./backend/ +RUN cd backend && npm install --no-audit --no-fund + +# Copy backend source code +COPY backend/ ./backend/ + +# Run tests +RUN cd backend && npm test + +# Stage 4: Final Production Image (minimal base) +FROM node:20-alpine AS production + +# Create non-root user first (before installing packages) +RUN addgroup -g 1001 -S app && \ + adduser -S app -u 1001 -G app + +# Install minimal runtime dependencies with size optimization +RUN apk add --no-cache --virtual .runtime-deps \ + sqlite \ + openssl \ + curl \ + dumb-init && \ + # Clean up package cache immediately + rm -rf /var/cache/apk/* /tmp/* && \ + # Remove unnecessary files + rm -rf /usr/share/man /usr/share/doc /usr/share/info + +# Set working directory +WORKDIR /app + +# Copy backend dependencies from deps stage (optimized) +COPY --from=backend-deps --chown=app:app /app/node_modules ./backend/node_modules + +# Copy backend application code (exclude unnecessary files) +COPY --chown=app:app backend/app.js ./backend/ +COPY --chown=app:app backend/package*.json ./backend/ +COPY --chown=app:app backend/config/ ./backend/config/ +COPY --chown=app:app backend/models/ ./backend/models/ +COPY --chown=app:app backend/routes/ ./backend/routes/ +COPY --chown=app:app backend/middleware/ ./backend/middleware/ +COPY --chown=app:app backend/services/ ./backend/services/ + +# Copy minimal built frontend assets from builder stage +COPY --from=frontend-builder --chown=app:app /app/dist ./backend/dist +COPY --from=frontend-builder --chown=app:app /app/public/locales ./backend/dist/locales + +# Create ultra-minimal startup script (before switching to non-root user) +RUN printf '#!/bin/sh\nset -e\ncd backend\nmkdir -p db certs\nDB_FILE="db/production.sqlite3"\n[ "$NODE_ENV" = "development" ] && DB_FILE="db/development.sqlite3"\nif [ ! -f "$DB_FILE" ]; then\n node -e "require(\\"./models\\").sequelize.sync({force:true}).then(()=>{console.log(\\"✅ DB ready\\");process.exit(0)}).catch(e=>{console.error(\\"❌\\",e.message);process.exit(1)})"\nelse\n node -e "require(\\"./models\\").sequelize.authenticate().then(()=>{console.log(\\"✅ DB OK\\");process.exit(0)}).catch(e=>{console.error(\\"❌\\",e.message);process.exit(1)})"\nfi\nif [ -n "$TUDUDI_USER_EMAIL" ]&&[ -n "$TUDUDI_USER_PASSWORD" ]; then\n node -e "const{User}=require(\\"./models\\");const bcrypt=require(\\"bcrypt\\");(async()=>{try{const[u,c]=await User.findOrCreate({where:{email:process.env.TUDUDI_USER_EMAIL},defaults:{email:process.env.TUDUDI_USER_EMAIL,password_digest:await bcrypt.hash(process.env.TUDUDI_USER_PASSWORD,10)}});console.log(c?\\"✅ User created\\":\\"ℹ️ User exists\\");process.exit(0)}catch(e){console.error(\\"❌\\",e.message);process.exit(1)}})();"||exit 1\nfi\n[ "$TUDUDI_INTERNAL_SSL_ENABLED" = "true" ]&&[ ! -f "certs/server.crt" ]&&openssl req -x509 -newkey rsa:2048 -keyout certs/server.key -out certs/server.crt -days 365 -nodes -subj "/CN=localhost" 2>/dev/null||true\nexec node app.js\n' > start.sh && chmod +x start.sh + +# Create necessary directories and final cleanup +RUN mkdir -p ./backend/db ./backend/certs && \ + chown -R app:app ./backend/db ./backend/certs ./start.sh && \ + # Final size optimization - remove Node.js build tools and cache + apk del --no-cache .runtime-deps sqlite openssl curl && \ + apk add --no-cache sqlite-libs openssl curl dumb-init && \ + rm -rf /usr/local/lib/node_modules/npm/docs /usr/local/lib/node_modules/npm/man && \ + rm -rf /root/.npm /tmp/* /var/tmp/* /var/cache/apk/* + +# Switch to non-root user USER app -# Expose ports for both frontend (8080) and backend (9292) -EXPOSE 8080 9292 +# Expose port +EXPOSE 3002 -# Set production environment variables -ENV RACK_ENV=production \ - NODE_ENV=production \ +# Set optimized production environment variables +ENV NODE_ENV=production \ + PORT=3002 \ TUDUDI_INTERNAL_SSL_ENABLED=false \ - TUDUDI_ALLOWED_ORIGINS="http://localhost:8080,http://localhost:9292,http://127.0.0.1:8080,http://127.0.0.1:9292,http://0.0.0.0:8080,http://0.0.0.0:9292" \ - LANG=C.UTF-8 \ - TZ=UTC + TUDUDI_ALLOWED_ORIGINS="http://localhost:8080,http://localhost:3002,http://127.0.0.1:8080,http://127.0.0.1:3002" \ + TUDUDI_SESSION_SECRET="" \ + TUDUDI_USER_EMAIL="" \ + TUDUDI_USER_PASSWORD="" \ + DISABLE_TELEGRAM=false \ + DISABLE_SCHEDULER=false -# Generate SSL certificates if needed -RUN mkdir -p certs && \ - if [ "$TUDUDI_INTERNAL_SSL_ENABLED" = "true" ]; then \ - openssl req -x509 -newkey rsa:4096 \ - -keyout certs/server.key -out certs/server.crt \ - -days 365 -nodes \ - -subj '/CN=localhost' \ - -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"; \ - fi +# Minimal healthcheck +HEALTHCHECK --interval=60s --timeout=3s --start-period=10s --retries=2 \ + CMD curl -sf http://localhost:3002/api/health || exit 1 -# Add healthcheck for backend -HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \ - CMD curl -f http://localhost:9292/api/health || exit 1 - -# Build production frontend assets -RUN npm run build - -# Copy translation files to dist folder for production serving -RUN cp -r public/locales dist/ - -# Create startup script -RUN echo '#!/bin/bash\n\ -set -e\n\ -\n\ -# Run database migrations\n\ -bundle exec rake db:migrate\n\ -\n\ -# Create user if it does not exist\n\ -if [ -n "$TUDUDI_USER_EMAIL" ] && [ -n "$TUDUDI_USER_PASSWORD" ]; then\n\ - echo "Creating user if it does not exist..."\n\ - echo "user = User.find_by(email: \"$TUDUDI_USER_EMAIL\") || User.create(email: \"$TUDUDI_USER_EMAIL\", password: \"$TUDUDI_USER_PASSWORD\"); puts \"User: #{user.email}\"" | bundle exec rake console\n\ -fi\n\ -\n\ -# Start backend with both API and static file serving\n\ -bundle exec puma -C app/config/puma.rb\n\ -' > start.sh && chmod +x start.sh - -# Run both services -CMD ["./start.sh"] \ No newline at end of file +# Use dumb-init for proper signal handling +ENTRYPOINT ["dumb-init", "--"] +CMD ["/app/start.sh"] \ No newline at end of file diff --git a/Gemfile b/Gemfile deleted file mode 100644 index 2f2d0d7..0000000 --- a/Gemfile +++ /dev/null @@ -1,28 +0,0 @@ -source 'https://rubygems.org' - -gem 'puma' -gem 'rack-protection', '~> 3.1.0' -gem 'rake', '~> 13.0' -gem 'rufus-scheduler', '~> 3.8.2' - -# DB -gem 'sinatra-activerecord' -gem 'sinatra-cross_origin' -gem 'sinatra-namespace' -gem 'sqlite3' - -# Authentication -gem 'bcrypt', '~> 3.1' - -# Other -gem 'byebug', '~> 11.1' -gem 'nokogiri', '~> 1.15' -gem 'rerun' - -# Development -gem 'faker' -gem 'rubocop' - -# Testing -gem 'minitest', group: :test -gem 'rack-test', group: :test diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index e12c402..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,146 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - activemodel (7.1.1) - activesupport (= 7.1.1) - activerecord (7.1.1) - activemodel (= 7.1.1) - activesupport (= 7.1.1) - timeout (>= 0.4.0) - activesupport (7.1.1) - base64 - bigdecimal - concurrent-ruby (~> 1.0, >= 1.0.2) - connection_pool (>= 2.2.5) - drb - i18n (>= 1.6, < 2) - minitest (>= 5.1) - mutex_m - tzinfo (~> 2.0) - ast (2.4.2) - base64 (0.2.0) - bcrypt (3.1.19) - bigdecimal (3.1.4) - byebug (11.1.3) - concurrent-ruby (1.2.2) - connection_pool (2.4.1) - drb (2.2.0) - ruby2_keywords - et-orbi (1.2.11) - tzinfo - faker (3.2.2) - i18n (>= 1.8.11, < 2) - ffi (1.16.3) - fugit (1.11.1) - et-orbi (~> 1, >= 1.2.11) - raabro (~> 1.4) - i18n (1.14.1) - concurrent-ruby (~> 1.0) - json (2.6.3) - language_server-protocol (3.17.0.3) - listen (3.8.0) - rb-fsevent (~> 0.10, >= 0.10.3) - rb-inotify (~> 0.9, >= 0.9.10) - minitest (5.20.0) - multi_json (1.15.0) - mustermann (3.0.0) - ruby2_keywords (~> 0.0.1) - mutex_m (0.2.0) - nio4r (2.5.9) - nokogiri (1.18.8-aarch64-linux-gnu) - racc (~> 1.4) - nokogiri (1.18.8-arm64-darwin) - racc (~> 1.4) - nokogiri (1.18.8-x86_64-linux-gnu) - racc (~> 1.4) - parallel (1.23.0) - parser (3.2.2.4) - ast (~> 2.4.1) - racc - puma (6.4.0) - nio4r (~> 2.0) - raabro (1.4.0) - racc (1.7.3) - rack (2.2.8) - rack-protection (3.1.0) - rack (~> 2.2, >= 2.2.4) - rack-test (2.1.0) - rack (>= 1.3) - rainbow (3.1.1) - rake (13.2.1) - rb-fsevent (0.11.2) - rb-inotify (0.10.1) - ffi (~> 1.0) - regexp_parser (2.8.2) - rerun (0.14.0) - listen (~> 3.0) - rexml (3.2.6) - rubocop (1.57.2) - json (~> 2.3) - language_server-protocol (>= 3.17.0) - parallel (~> 1.10) - parser (>= 3.2.2.4) - rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.28.1, < 2.0) - ruby-progressbar (~> 1.7) - unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.30.0) - parser (>= 3.2.1.0) - ruby-progressbar (1.13.0) - ruby2_keywords (0.0.5) - rufus-scheduler (3.8.2) - fugit (~> 1.1, >= 1.1.6) - sinatra (3.1.0) - mustermann (~> 3.0) - rack (~> 2.2, >= 2.2.4) - rack-protection (= 3.1.0) - tilt (~> 2.0) - sinatra-activerecord (2.0.27) - activerecord (>= 4.1) - sinatra (>= 1.0) - sinatra-contrib (3.1.0) - multi_json - mustermann (~> 3.0) - rack-protection (= 3.1.0) - sinatra (= 3.1.0) - tilt (~> 2.0) - sinatra-cross_origin (0.4.0) - sinatra-namespace (1.0) - sinatra-contrib - sqlite3 (1.6.8-aarch64-linux) - sqlite3 (1.6.8-arm64-darwin) - sqlite3 (1.6.8-x86_64-linux) - tilt (2.3.0) - timeout (0.4.1) - tzinfo (2.0.6) - concurrent-ruby (~> 1.0) - unicode-display_width (2.5.0) - -PLATFORMS - aarch64-linux - arm64-darwin-22 - arm64-darwin-24 - x86_64-linux - -DEPENDENCIES - bcrypt (~> 3.1) - byebug (~> 11.1) - faker - minitest - nokogiri (~> 1.15) - puma - rack-protection (~> 3.1.0) - rack-test - rake (~> 13.0) - rerun - rubocop - rufus-scheduler (~> 3.8.2) - sinatra-activerecord - sinatra-cross_origin - sinatra-namespace - sqlite3 - -BUNDLED WITH - 2.4.21 diff --git a/README.md b/README.md index 6252060..f5c581c 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ This app allows users to manage their tasks, projects, areas, notes, and tags in an organized way. Users can create tasks, projects, areas (to group projects), notes, and tags. Each task can be associated with a project, and both tasks and notes can be tagged for better organization. Projects can belong to areas and can also have multiple notes and tags. This structure helps users categorize and track their work efficiently, whether they’re managing individual tasks, larger projects, or keeping detailed notes. + ## ✨ Features - **Task Management**: Create, update, and delete tasks. Mark tasks as completed and view them by different filters (Today, Upcoming, Someday). Order them by Name, Due Date, Date Created, or Priority. @@ -35,9 +36,9 @@ Check out our [GitHub Project](https://github.com/users/chrisvel/projects/2) for ## 🛠️ Getting Started -**One simple command**, that's all it takes to run tududi with _docker_. +### Quick Start with Docker -### 🐋 Docker +**One simple command**, that's all it takes to run tududi with Docker. First pull the latest image: @@ -58,7 +59,7 @@ The following environment variables are used to configure tududi: - `TUDUDI_INTERNAL_SSL_ENABLED` - Set to 'true' if using HTTPS internally (default: false) - `TUDUDI_ALLOWED_ORIGINS` - Controls CORS access for different deployment scenarios: - Not set: Only allows localhost origins - - Specific domains: `https://tududi.com,http://localhost:9292` + - Specific domains: `https://tududi.com,http://localhost:3002` - Allow all (development only): Set to empty string `""` #### Common Configuration Examples: @@ -89,23 +90,31 @@ docker run \ -e TUDUDI_USER_PASSWORD=mysecurepassword \ -e TUDUDI_SESSION_SECRET=$(openssl rand -hex 64) \ -e TUDUDI_INTERNAL_SSL_ENABLED=false \ - -e TUDUDI_ALLOWED_ORIGINS=https://tududi,http://tududi:9292 \ - -v ~/tududi_db:/usr/src/app/tududi_db \ - -p 9292:9292 \ + -e TUDUDI_ALLOWED_ORIGINS=https://tududi,http://tududi:3002 \ + -v ~/tududi_db:/usr/src/app/backend/db \ + -p 3002:3002 \ -d chrisvel/tududi:latest ``` -Navigate to [https://localhost:9292](https://localhost:9292) and login with your credentials. +Navigate to [http://localhost:3002](http://localhost:3002) and login with your credentials. + +### 🔑 Authentication + +The application uses session-based authentication with secure cookies. For development: +- Frontend runs on port 8080 with webpack dev server +- Backend runs on port 3001 and handles authentication +- CORS is configured to allow cross-origin requests during development +- In production (Docker), both frontend and backend run on the same port (3002) ## 🚧 Development ### Prerequisites Before you begin, ensure you have the following installed: -- Ruby (version 3.2.2 or higher) -- Sinatra +- Node.js (version 20 or higher) +- Express.js - SQLite3 -- Puma +- npm - ReactJS ### 🏗 Installation @@ -120,59 +129,165 @@ To install `tududi`, follow these steps: ```bash cd tududi ``` -3. Install the required gems: +3. Install the required dependencies: ```bash - bundle install + # Install frontend dependencies + npm install + + # Install backend dependencies + cd backend + npm install + cd .. ``` -### 🔒 SSL Setup +### 🔒 SSL Setup (Optional) + +For HTTPS support, create SSL certificates: 1. Create and enter the directory: ```bash - mkdir certs - cd certs + mkdir backend/certs + cd backend/certs ``` 2. Create the key and cert: ```bash openssl genrsa -out server.key 2048 openssl req -new -x509 -key server.key -out server.crt -days 365 + cd ../.. ``` ### 📂 Database Setup -Execute the migrations: +The database will be automatically initialized when you start the Express backend. For manual database operations: -```bash -rake db:migrate +```bash +cd backend + +# Initialize database (creates tables, drops existing data) +npm run db:init + +# Sync database (creates tables if they don't exist) +npm run db:sync + +# Migrate database (alters existing tables to match models) +npm run db:migrate + +# Reset database (drops and recreates all tables) +npm run db:reset + +# Check database status and connection +npm run db:status + +cd .. ``` -### 👤 Create Your User +### 🔄 Database Migrations -1. Open the console: - ```bash - rake console - ``` -2. Add the user: - ```ruby - User.create(email: "myemail@somewhere.com", password: "awes0meHax0Rp4ssword") - ``` +For schema changes, use Sequelize migrations (similar to Rails/Ruby migrations): + +```bash +cd backend + +# Create a new migration +npm run migration:create add-description-to-tasks + +# Run pending migrations +npm run migration:run + +# Check migration status +npm run migration:status + +# Rollback last migration +npm run migration:undo + +# Rollback all migrations +npm run migration:undo:all + +cd .. +``` + +#### Creating a New Migration Example: +```bash +# 1. Create the migration file +npm run migration:create add-priority-to-projects + +# 2. Edit the generated file in migrations/ folder: +# - Add your schema changes in the 'up' function +# - Add rollback logic in the 'down' function + +# 3. Run the migration +npm run migration:run +``` + +### 👤 User Setup + +#### For Development + +Set environment variables to automatically create the initial user: + +```bash +export TUDUDI_USER_EMAIL=dev@example.com +export TUDUDI_USER_PASSWORD=password123 +export TUDUDI_SESSION_SECRET=$(openssl rand -hex 64) +``` + +Or create a user manually: +```bash +cd backend +npm run user:create dev@example.com password123 +cd .. +``` + +#### Default Development Credentials + +If no environment variables are set, you can use the default development credentials: +- Email: `dev@example.com` +- Password: `password123` ### 🚀 Usage -To start the application, run: +To start the application for development: -```bash -puma -C app/config/puma.rb -``` +1. **Start the Express backend** (in one terminal): + ```bash + cd backend + npm run dev # Development mode with auto-reload + # Or: npm start # Production mode + ``` + The backend will run on `http://localhost:3001` + +2. **Start the frontend development server** (in another terminal): + ```bash + npm run dev + ``` + The frontend will run on `http://localhost:8080` + +3. **Access the application**: Open your browser to `http://localhost:8080` + +### Port Configuration + +- **Development Frontend**: `http://localhost:8080` (webpack dev server) +- **Development Backend**: `http://localhost:3001` (Express API server) +- **Docker/Production**: `http://localhost:3002` (combined frontend + backend) + +The webpack dev server automatically proxies API calls and locales to the backend server. ### 🔍 Testing -To run tests, execute: +To run tests: ```bash -bundle exec ruby -Itest test/test_app.rb +# Backend tests +cd backend +npm test + +# Frontend tests +cd .. +npm test ``` +Note: Test suites are currently being migrated from the Ruby/Sinatra implementation. + ## 🤝 Contributing Contributions to `tududi` are welcome. To contribute: diff --git a/Rakefile b/Rakefile deleted file mode 100644 index 7be69c7..0000000 --- a/Rakefile +++ /dev/null @@ -1,12 +0,0 @@ -require 'irb' - -require 'sinatra/activerecord' -require 'sinatra/activerecord/rake' - -require './app' - -desc 'Start an interactive console' -task :console do - ARGV.clear - IRB.start -end \ No newline at end of file diff --git a/app.rb b/app.rb deleted file mode 100644 index 891c180..0000000 --- a/app.rb +++ /dev/null @@ -1,208 +0,0 @@ -require 'sinatra' -require 'sinatra/activerecord' -require 'securerandom' -require 'byebug' - -# Models -require './app/models/user' -require './app/models/area' -require './app/models/project' -require './app/models/task' -require './app/models/tag' -require './app/models/note' -require './app/models/inbox_item' - -# Services -require './app/services/task_summary_service' -require './app/services/url_title_extractor_service' -require './config/initializers/scheduler' -require './config/initializers/telegram_initializer' - -# Helpers -require './app/helpers/authentication_helper' -require './app/routes/authentication_routes' -require './app/routes/tasks_routes' -require './app/routes/projects_routes' -require './app/routes/areas_routes' -require './app/routes/notes_routes' -require './app/routes/tags_routes' -require './app/routes/users_routes' -require './app/routes/inbox_routes' -require './app/routes/telegram_poller' -require './app/routes/telegram_routes' -require './app/routes/url_routes' - -require 'sinatra/cross_origin' - -helpers AuthenticationHelper - -use Rack::MethodOverride - -set :database_file, './app/config/database.yml' -set :views, proc { File.join(root, 'app/views') } -set :public_folder, production? ? 'dist' : 'public' - -configure do - enable :cross_origin - enable :sessions - - # Session configuration - secure_flag = production? && ENV['TUDUDI_INTERNAL_SSL_ENABLED'] == 'true' - set :sessions, httponly: true, - secure: secure_flag, - expire_after: 2_592_000, - same_site: secure_flag ? :none : :lax - set :session_secret, ENV.fetch('TUDUDI_SESSION_SECRET') { SecureRandom.hex(64) } - - # CORS configuration - use environment variable in production, fallback to localhost for development - allowed_origins = if ENV['TUDUDI_ALLOWED_ORIGINS'] - ENV['TUDUDI_ALLOWED_ORIGINS'].split(',').map(&:strip) - else - ['http://localhost:8080', 'http://localhost:9292', 'http://127.0.0.1:8080', 'http://127.0.0.1:9292'] - end - set :allow_origin, allowed_origins - set :allow_methods, %i[get post patch delete options] - set :allow_credentials, true - set :max_age, '1728000' - set :expose_headers, ['Content-Type'] - set :allow_headers, %w[Authorization Content-Type Accept X-Requested-With] - - # Ensure ActiveRecord connection is established - ActiveRecord::Base.establish_connection - - # Auto-create user if not exists - if ENV['TUDUDI_USER_EMAIL'] && ENV['TUDUDI_USER_PASSWORD'] && ActiveRecord::Base.connection.table_exists?('users') - user = User.find_or_initialize_by(email: ENV['TUDUDI_USER_EMAIL']) - if user.new_record? - user.password = ENV['TUDUDI_USER_PASSWORD'] - user.save - end - end - - # Initialize the Telegram polling after database is ready - initialize_telegram_polling -end - -# Rack Protection configuration - completely disable for development -if development? - # Disable Rack::Protection completely in development to avoid CSRF issues - set :protection, false -else - # Use the same allowed origins for Rack::Protection in production - use Rack::Protection, - except: %i[remote_token session_hijacking remote_referrer], - origin_whitelist: settings.allow_origin -end - -before do - # Handle CORS preflight requests - if request.request_method == 'OPTIONS' - response.headers['Access-Control-Allow-Methods'] = settings.allow_methods.map(&:to_s).join(', ') - response.headers['Access-Control-Allow-Headers'] = settings.allow_headers.join(', ') - response.headers['Access-Control-Max-Age'] = settings.max_age - halt 200 - end - - # Set CORS headers for all requests - if request.env['HTTP_ORIGIN'] && settings.allow_origin.include?(request.env['HTTP_ORIGIN']) - response.headers['Access-Control-Allow-Origin'] = request.env['HTTP_ORIGIN'] - response.headers['Access-Control-Allow-Credentials'] = 'true' - response.headers['Access-Control-Expose-Headers'] = settings.expose_headers.join(', ') - end - - # Authentication check - only for API routes - if request.path_info.start_with?('/api/') && !['/api/login', '/api/health'].include?(request.path_info) - require_login - end -end - -helpers do - def current_path - request.path_info - end - - def partial(page, options = {}) - erb page, options.merge!(layout: false) - end - - def nav_link_active?(path, query_params = {}, project_id = nil) - current_uri = request.path_info - current_query = request.query_string - current_params = Rack::Utils.parse_nested_query(current_query) - is_project_page = current_uri.include?('/project/') && path.include?('/project/') - - if is_project_page - current_uri == path && (!project_id || current_uri.end_with?("/#{project_id}")) - elsif !query_params.empty? - current_uri == path && query_params.all? { |k, v| current_params[k] == v } - else - current_uri == path && current_params.empty? - end - end - - def nav_link(path, query_params = {}, project_id = nil) - is_active = nav_link_active?(path, query_params, project_id) - - classes = 'nav-link py-1 px-3' - classes += ' active-link' if is_active - - classes - end - - def update_query_params(key, value) - uri = URI(request.url) - params = Rack::Utils.parse_nested_query(uri.query) - params[key] = value - Rack::Utils.build_query(params) - end - - def url_without_tag - uri = URI(request.url) - params = Rack::Utils.parse_nested_query(uri.query) - params.delete('tag') # Remove the 'tag' parameter - uri.query = Rack::Utils.build_query(params) - uri.to_s - end -end - -get '/' do - if settings.production? - # In production, serve the built index.html directly - send_file File.join(settings.public_folder, 'index.html') - else - # In development, use ERB template - erb :index - end -end - -# Catch-all route for SPA routing in production -get '*' do - # Skip API routes and static assets - unless request.path_info.start_with?('/api/') || request.path_info.match(/\.(js|css|png|jpg|jpeg|gif|ico|svg)$/) - if settings.production? - # In production, serve the built index.html for all SPA routes - send_file File.join(settings.public_folder, 'index.html') - else - # In development, use ERB template - erb :index - end - end -end - -# Health check endpoint for Docker -get '/api/health' do - content_type :json - { status: 'ok', timestamp: Time.now.iso8601 }.to_json -end - -# Catch-all route for non-API routes to serve the SPA -get '*' do - pass if request.path_info.start_with?('/api/') - erb :index -end - -not_found do - content_type :json - status 404 - { error: 'Not Found', message: 'The requested resource could not be found.' }.to_json -end diff --git a/app/config/database.yml b/app/config/database.yml deleted file mode 100644 index 3eea98c..0000000 --- a/app/config/database.yml +++ /dev/null @@ -1,17 +0,0 @@ -# config/database.yml -default: &default - adapter: sqlite3 - pool: 15 - timeout: 5000 - -development: - <<: *default - database: db/development.sqlite3 - -test: - <<: *default - database: db/test.sqlite3 - -production: - <<: *default - database: tududi_db/production.sqlite3 diff --git a/app/config/puma.rb b/app/config/puma.rb deleted file mode 100644 index 5362ee1..0000000 --- a/app/config/puma.rb +++ /dev/null @@ -1,9 +0,0 @@ -if ENV['TUDUDI_INTERNAL_SSL_ENABLED'] == 'true' - ssl_bind '0.0.0.0', '9292', { - key: 'certs/server.key', - cert: 'certs/server.crt', - verify_mode: 'none' - } -else - bind 'tcp://0.0.0.0:9292' -end diff --git a/app/helpers/authentication_helper.rb b/app/helpers/authentication_helper.rb deleted file mode 100644 index dfc2c9b..0000000 --- a/app/helpers/authentication_helper.rb +++ /dev/null @@ -1,21 +0,0 @@ -module AuthenticationHelper - def logged_in? - !!session[:user_id] - end - - def current_user - @current_user ||= User.find(session[:user_id]) if session[:user_id] - end - - def require_login - return if ['/api/login', '/api/logout', '/api/current_user'].include?(request.path_info) - - return if logged_in? - - if request.xhr? || request.path_info.start_with?('/api/') - halt 401, { error: 'You must be logged in' }.to_json - else - redirect '/login' - end - end -end diff --git a/app/models/area.rb b/app/models/area.rb deleted file mode 100644 index 84b8a0f..0000000 --- a/app/models/area.rb +++ /dev/null @@ -1,6 +0,0 @@ -class Area < ActiveRecord::Base - belongs_to :user - has_many :projects, dependent: :destroy - - validates :name, presence: true, uniqueness: { scope: :user_id } -end diff --git a/app/models/inbox_item.rb b/app/models/inbox_item.rb deleted file mode 100644 index 89e7318..0000000 --- a/app/models/inbox_item.rb +++ /dev/null @@ -1,22 +0,0 @@ -class InboxItem < ActiveRecord::Base - belongs_to :user - - enum status: { added: 'added', processed: 'processed', deleted: 'deleted' } - enum source: { tududi: 'tududi', telegram: 'telegram' } - - scope :active, -> { where(status: 'added') } - scope :processed, -> { where(status: 'processed') } - scope :by_source, ->(source) { where(source: source) } - - validates :content, presence: true - validates :status, inclusion: { in: statuses.keys } - validates :source, inclusion: { in: sources.keys } - - def mark_as_processed! - update(status: 'processed') - end - - def mark_as_deleted! - update(status: 'deleted') - end -end diff --git a/app/models/note.rb b/app/models/note.rb deleted file mode 100644 index 5338d7f..0000000 --- a/app/models/note.rb +++ /dev/null @@ -1,8 +0,0 @@ -class Note < ActiveRecord::Base - belongs_to :user - belongs_to :project, optional: true - has_and_belongs_to_many :tags - - validates :content, presence: true - validates :title, presence: true, uniqueness: { scope: :user_id } -end diff --git a/app/models/project.rb b/app/models/project.rb deleted file mode 100644 index db73f0f..0000000 --- a/app/models/project.rb +++ /dev/null @@ -1,39 +0,0 @@ -class Project < ActiveRecord::Base - belongs_to :user - belongs_to :area, optional: true - has_many :tasks, dependent: :destroy - has_many :notes, dependent: :destroy - has_and_belongs_to_many :tags - - enum priority: { low: 0, medium: 1, high: 2 } - - scope :with_incomplete_tasks, -> { joins(:tasks).where.not(tasks: { status: Task.statuses[:done] }).distinct } - scope :with_complete_tasks, -> { joins(:tasks).where(tasks: { status: Task.statuses[:done] }).distinct } - - validates :name, presence: true, uniqueness: { scope: :user_id } - - def task_status_counts - status_counts = tasks.group(:status).count - - total = status_counts.values.sum - - { - total: total, - in_progress: status_counts['in_progress'] || 0, - done: status_counts['done'] || 0, - not_started: status_counts['not_started'] || 0 - } - end - - def progress_percentage - counts = task_status_counts - return 0 if counts[:total].zero? - - completed_tasks = counts[:total] - counts[:not_started] - (completed_tasks.to_f / counts[:total] * 100).round - end - - def due_date_at - self[:due_date_at]&.strftime('%Y-%m-%d') - end -end diff --git a/app/models/tag.rb b/app/models/tag.rb deleted file mode 100644 index a5662ad..0000000 --- a/app/models/tag.rb +++ /dev/null @@ -1,8 +0,0 @@ -class Tag < ActiveRecord::Base - belongs_to :user - has_and_belongs_to_many :tasks - has_and_belongs_to_many :notes - has_and_belongs_to_many :projects - - validates :name, presence: true, uniqueness: { scope: :user_id } -end diff --git a/app/models/task.rb b/app/models/task.rb deleted file mode 100644 index f89b74e..0000000 --- a/app/models/task.rb +++ /dev/null @@ -1,178 +0,0 @@ -class Task < ActiveRecord::Base - belongs_to :user - belongs_to :project, optional: true - has_and_belongs_to_many :tags - - enum priority: { low: 0, medium: 1, high: 2 } - enum status: { not_started: 0, in_progress: 1, done: 2, archived: 3, waiting: 4 } - - scope :complete, -> { where(status: statuses[:done]) } - scope :incomplete, -> { where.not(status: statuses[:done]) } - scope :due_today, -> { incomplete.where('DATE(due_date) <= ?', Date.today) } - scope :upcoming, -> { incomplete.where('due_date BETWEEN ? AND ?', Date.today, Date.today + 7.days) } - scope :someday, -> { incomplete.where(due_date: nil) } - scope :next_actions, -> { incomplete.where(due_date: nil, project_id: nil) } - scope :waiting_for, -> { incomplete.where(status: statuses[:waiting]) } - scope :inbox, -> { incomplete.where('due_date IS NULL OR project_id IS NULL') } - - scope :ordered_by_due_date, lambda { |direction = 'asc'| - order(Arel.sql("CASE WHEN due_date IS NULL THEN 1 ELSE 0 END, due_date #{direction}")) - } - - scope :with_tag, lambda { |tag_name| - joins(:tags).where(tags: { name: tag_name }) - } - - scope :by_status, ->(status) { where(status: statuses[status]) } - scope :by_priority, ->(priority) { where(priority: priorities[priority]) } - - scope :order_by_priority, -> { order(priority: :desc) } - - validates :name, presence: true, uniqueness: { scope: :user_id } - - def self.filter_by_params(params, user) - tasks = user.tasks.includes(:project, :tags) - - tasks = case params[:type] - when 'today' - tasks - when 'upcoming' - tasks.upcoming - when 'next' - tasks.next_actions - when 'inbox' - tasks.inbox - when 'someday' - tasks.someday - when 'waiting' - tasks.waiting_for - else - params[:status] == 'done' ? tasks.complete : tasks.incomplete - end - - tasks = tasks.with_tag(params[:tag]) if params[:tag] - - tasks = tasks.apply_ordering(params[:order_by]) if params[:order_by] - - tasks.left_joins(:tags).distinct - end - - scope :apply_ordering, lambda { |order_by| - order_column, order_direction = order_by.split(':') - order_direction ||= 'asc' - order_direction = order_direction.downcase == 'desc' ? :desc : :asc - - allowed_columns = %w[created_at updated_at name priority status due_date] - raise ArgumentError, 'Invalid order column specified.' unless allowed_columns.include?(order_column) - - if order_column == 'due_date' - ordered_by_due_date(order_direction) - else - order("tasks.#{order_column} #{order_direction}") - end - } - - def self.compute_metrics(user) - total_open_tasks = user.tasks.incomplete.count - one_month_ago = Date.today - 30 - tasks_pending_over_month = user.tasks.incomplete.where('created_at < ?', one_month_ago).count - - tasks_in_progress = user.tasks.incomplete.where(status: statuses[:in_progress]).order(priority: :desc) - tasks_in_progress_count = tasks_in_progress.count - - # Calculate tasks due today including those due via projects - tasks_due_today = user.tasks.incomplete.joins(:project) - .where('tasks.due_date <= ? OR projects.due_date_at <= ?', Date.today, Date.today) - .distinct - - # Gather an array of IDs to be excluded from suggested tasks - excluded_task_ids = tasks_in_progress.pluck(:id) + tasks_due_today.pluck(:id) - - # Gather tasks in projects expiring starting today, order by task priority - tasks_in_expiring_projects = user.tasks.incomplete - .joins(:project) - .where('projects.due_date_at >= ?', Date.today) - .where(projects: { active: true }) # Only active projects - .where.not(id: excluded_task_ids) - .order(Arel.sql('projects.due_date_at ASC, tasks.priority DESC')) - .limit(5) - - # Gather tasks not assigned to projects expiring today, ordered by task priority - tasks_without_projects = user.tasks.incomplete - .where(status: statuses[:not_started], project_id: nil) - .or(user.tasks.where(project_id: nil, status: statuses[:not_started])) - .where.not(id: excluded_task_ids) - .order(priority: :desc) - .limit(5) - - # Combine both list of suggested tasks - suggested_tasks = sort_suggested_tasks(tasks_in_expiring_projects + tasks_without_projects) - { - total_open_tasks: total_open_tasks, - tasks_pending_over_month: tasks_pending_over_month, - tasks_in_progress: tasks_in_progress, - tasks_in_progress_count: tasks_in_progress_count, - tasks_due_today: tasks_due_today, - suggested_tasks: suggested_tasks - } - end - - def self.sort_suggested_tasks(tasks) - tasks.sort_by do |task| - # Parse or default the task due date - task_due_date = if task.due_date.is_a?(String) - Date.parse(task.due_date) - else - task.due_date || Date.new(9999, 12, 31) - end - - # Parse or default the project due date - project_due_date = if task.project&.due_date_at.is_a?(String) - Date.parse(task&.project&.due_date_at) - else - task.project&.due_date_at || Date.new(9999, 12, 31) - end - - # Priority in descending order (sorted values should be negative for sort_by) - priority_value = -Task.priorities.fetch(task.priority, -1) - - # Determine sorting flags based on various criteria - is_high_priority_proj_with_due_date = task.priority == 'high' && task&.project&.due_date_at ? 0 : 1 - is_high_priority_with_due_date = task.priority == 'high' && task.due_date ? 0 : 1 - is_high_priority = task.priority == 'high' && !task.due_date && !task&.project&.due_date_at ? 0 : 1 - - is_medium_priority_proj_with_due_date = task.priority == 'medium' && task&.project&.due_date_at ? 0 : 1 - is_medium_priority_with_due_date = task.priority == 'medium' && task.due_date ? 0 : 1 - is_medium_priority = task.priority == 'medium' && !task.due_date && !task&.project&.due_date_at ? 0 : 1 - - is_low_priority_proj_with_due_date = task.priority == 'low' && task&.project&.due_date_at ? 0 : 1 - is_low_priority_with_due_date = task.priority == 'low' && task.due_date ? 0 : 1 - is_low_priority = task.priority == 'low' && !task.due_date && !task&.project&.due_date_at ? 0 : 1 - - # Primary sorting criteria - [ - is_high_priority_proj_with_due_date, - is_high_priority_with_due_date, - is_high_priority, - - is_medium_priority_proj_with_due_date, - is_medium_priority_with_due_date, - is_medium_priority, - - is_low_priority_proj_with_due_date, - is_low_priority_with_due_date, - is_low_priority, - - task_due_date, - project_due_date, - priority_value - ] - end - end - - def as_json(options = {}) - super(options).merge( - 'due_date' => due_date&.strftime('%Y-%m-%d') - ) - end -end diff --git a/app/models/user.rb b/app/models/user.rb deleted file mode 100644 index d95a156..0000000 --- a/app/models/user.rb +++ /dev/null @@ -1,20 +0,0 @@ -class User < ActiveRecord::Base - has_secure_password - - TASK_SUMMARY_FREQUENCIES = %w[daily weekdays weekly 1h 2h 4h 8h 12h].freeze - - has_many :tasks, dependent: :destroy - has_many :projects, dependent: :destroy - has_many :areas, dependent: :destroy - has_many :notes, dependent: :destroy - has_many :tags, dependent: :destroy - has_many :inbox_items, dependent: :destroy - - validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }, uniqueness: true - validates :appearance, inclusion: { in: %w[light dark] } - validates :language, presence: true - validates :timezone, presence: true - validates :task_summary_frequency, inclusion: { in: TASK_SUMMARY_FREQUENCIES }, allow_nil: true - - # has_one_attached :avatar_image -end diff --git a/app/routes/areas_routes.rb b/app/routes/areas_routes.rb deleted file mode 100644 index 14abc98..0000000 --- a/app/routes/areas_routes.rb +++ /dev/null @@ -1,74 +0,0 @@ -require 'sinatra' -require 'json' - -post '/api/areas' do - content_type :json - begin - request_body = request.body.read - area_data = JSON.parse(request_body, symbolize_names: true) - - halt 400, { error: 'Area name is required.' }.to_json unless area_data[:name] && !area_data[:name].strip.empty? - - area = current_user.areas.build(name: area_data[:name], description: area_data[:description]) - - if area.save - status 201 - area.to_json - else - status 400 - { error: 'There was a problem creating the area.', details: area.errors.full_messages }.to_json - end - rescue JSON::ParserError - halt 400, { error: 'Invalid JSON.' }.to_json - end -end - -get '/api/areas/:id' do - area = current_user.areas.find_by(id: params[:id]) - halt 404, { error: "Area not found or doesn't belong to the current user." }.to_json unless area - area.to_json -end - -patch '/api/areas/:id' do - content_type :json - begin - area = current_user.areas.find_by(id: params[:id]) - halt 404, { error: 'Area not found.' }.to_json unless area - - request_body = request.body.read - area_data = JSON.parse(request_body, symbolize_names: true) - - # Update Area attributes - area.name = area_data[:name] if area_data[:name] - area.description = area_data[:description] if area_data[:description] - - if area.save - status 200 - area.to_json - else - status 400 - { error: 'There was a problem updating the area.', details: area.errors.full_messages }.to_json - end - rescue JSON::ParserError - halt 400, { error: 'Invalid JSON.' }.to_json - end -end - -delete '/api/areas/:id' do - content_type :json - area = current_user.areas.find_by(id: params[:id]) - halt 404, { error: 'Area not found.' }.to_json unless area - - if area.destroy - status 204 - else - status 400 - { error: 'There was a problem deleting the area.' }.to_json - end -end - -get '/api/areas' do - content_type :json - areas = current_user.areas - areas.to_json -end diff --git a/app/routes/authentication_routes.rb b/app/routes/authentication_routes.rb deleted file mode 100644 index cc20eaa..0000000 --- a/app/routes/authentication_routes.rb +++ /dev/null @@ -1,49 +0,0 @@ -require 'json' - -class Sinatra::Application - get '/api/current_user' do - content_type :json - - if logged_in? - { user: { email: current_user.email, id: current_user.id, language: current_user.language, - appearance: current_user.appearance, timezone: current_user.timezone } }.to_json - else - { user: nil }.to_json - end - end - - post '/api/login' do - content_type :json - request_payload = begin - JSON.parse(request.body.read) - rescue StandardError - nil - end - - if request_payload - email = request_payload['email'] - password = request_payload['password'] - else - halt 400, { error: 'Invalid login parameters.' }.to_json - end - - user = User.find_by(email: email) - if user&.authenticate(password) - session[:user_id] = user.id - status 200 - { user: { email: user.email, id: user.id, language: user.language, appearance: user.appearance, - timezone: user.timezone } }.to_json - else - halt 401, { errors: ['Invalid credentials'] }.to_json - end - end - - get '/api/logout' do - session.clear - status 200 - { message: 'Logged out successfully' }.to_json - end - # session.clear - # redirect '/login' - # end -end diff --git a/app/routes/inbox_routes.rb b/app/routes/inbox_routes.rb deleted file mode 100644 index f955dfa..0000000 --- a/app/routes/inbox_routes.rb +++ /dev/null @@ -1,92 +0,0 @@ -module Sinatra - class Application - get '/api/inbox' do - content_type :json - - items = current_user.inbox_items.where(status: 'added').order(created_at: :desc) - items.to_json - end - - post '/api/inbox' do - content_type :json - - request_body = request.body.read - item_data = begin - JSON.parse(request_body) - rescue JSON::ParserError => e - halt 400, { error: 'Invalid JSON format.' }.to_json - end - - item = current_user.inbox_items.build( - content: item_data['content'], - source: item_data['source'] || 'tududi' - ) - - if item.save - status 201 - item.to_json - else - errors = item.errors.full_messages - halt 400, { error: 'There was a problem creating the inbox item.', details: errors }.to_json - end - end - - patch '/api/inbox/:id' do - content_type :json - - item = current_user.inbox_items.find_by(id: params[:id]) - halt 404, { error: 'Inbox item not found.' }.to_json unless item - - request_body = request.body.read - item_data = begin - JSON.parse(request_body) - rescue JSON::ParserError => e - halt 400, { error: 'Invalid JSON format.' }.to_json - end - - if item.update(content: item_data['content']) - item.to_json - else - errors = item.errors.full_messages - halt 400, { error: 'There was a problem updating the inbox item.', details: errors }.to_json - end - end - - patch '/api/inbox/:id/process' do - content_type :json - - item = current_user.inbox_items.find_by(id: params[:id]) - halt 404, { error: 'Inbox item not found.' }.to_json unless item - - if item.mark_as_processed! - item.to_json - else - halt 400, { error: 'There was a problem processing the inbox item.' }.to_json - end - end - - # Mark an inbox item as deleted - delete '/api/inbox/:id' do - content_type :json - - item = current_user.inbox_items.find_by(id: params[:id]) - halt 404, { error: 'Inbox item not found.' }.to_json unless item - - if item.mark_as_deleted! - { message: 'Inbox item successfully deleted' }.to_json - else - halt 400, { error: 'There was a problem deleting the inbox item.' }.to_json - end - end - - # Get a specific inbox item by ID - get '/api/inbox/:id' do - content_type :json - - item = current_user.inbox_items.find_by(id: params[:id]) - halt 404, { error: 'Inbox item not found.' }.to_json unless item - - item.to_json - end - end -end diff --git a/app/routes/notes_routes.rb b/app/routes/notes_routes.rb deleted file mode 100644 index 23f92fa..0000000 --- a/app/routes/notes_routes.rb +++ /dev/null @@ -1,134 +0,0 @@ -class Sinatra::Application - def update_note_tags(note, tags_array) - return if tags_array.blank? - - begin - tag_names = tags_array.uniq - tags = tag_names.map do |name| - current_user.tags.find_or_create_by(name: name) - end - note.tags = tags - rescue StandardError => e - puts "Failed to update tags: #{e.message}" - end - end - - get '/api/notes' do - order_by = params[:order_by] || 'title:asc' - order_column, order_direction = order_by.split(':') - - @notes = current_user.notes.includes(:tags) - @notes = @notes.joins(:tags).where(tags: { name: params[:tag] }) if params[:tag] - @notes = @notes.order("notes.#{order_column} #{order_direction}") - - query_params = Rack::Utils.parse_nested_query(request.query_string) - query_params.delete('tag') - @base_query = query_params.to_query - @base_url = '/notes?' - @base_url += "#{@base_query}&" unless @base_query.empty? - - @notes.to_json(include: :tags) - end - - get '/api/note/:id' do - content_type :json - note = current_user.notes.includes(:tags).find_by(id: params[:id]) - - halt 404, { error: 'Note not found.' }.to_json unless note - - note.to_json(include: :tags) - end - - post '/api/note' do - content_type :json - - request_body = request.body.read - note_data = JSON.parse(request_body, symbolize_names: true) - - note_attributes = { - title: note_data[:title], - content: note_data[:content], - user_id: current_user.id - } - - if note_data[:project_id].to_s.empty? - note = current_user.notes.build(note_attributes) - else - project = current_user.projects.find_by(id: note_data[:project_id]) - halt 400, { error: 'Invalid project.' }.to_json unless project - note = project.notes.build(note_attributes) - end - - if note.save - # Handle tags array whether it's an array of strings or an array of objects with name property - tag_names = if note_data[:tags].is_a?(Array) && note_data[:tags].all? { |t| t.is_a?(String) } - note_data[:tags] - elsif note_data[:tags].is_a?(Array) && note_data[:tags].all? { |t| t.is_a?(Hash) && t[:name] } - note_data[:tags].map { |t| t[:name] } - else - [] - end - - update_note_tags(note, tag_names) - status 201 - note.to_json(include: :tags) - else - status 400 - { error: 'There was a problem creating the note.', details: note.errors.full_messages }.to_json - end - end - - patch '/api/note/:id' do - content_type :json - note = current_user.notes.find_by(id: params[:id]) - halt 404, { error: 'Note not found.' }.to_json unless note - - request_body = request.body.read - request_data = JSON.parse(request_body) - - note_attributes = { - title: request_data['title'], - content: request_data['content'] - } - - if request_data['project_id'] && !request_data['project_id'].to_s.empty? - project = current_user.projects.find_by(id: request_data['project_id']) - halt 400, { error: 'Invalid project.' }.to_json unless project - note.project = project - else - note.project = nil - end - - if note.update(note_attributes) - # Handle tags array whether it's an array of strings or an array of objects with name property - tag_names = if request_data['tags'].is_a?(Array) && request_data['tags'].all? { |t| t.is_a?(String) } - request_data['tags'] - elsif request_data['tags'].is_a?(Array) && request_data['tags'].all? do |t| - t.is_a?(Hash) && t['name'] - end - request_data['tags'].map { |t| t['name'] } - else - [] - end - - update_note_tags(note, tag_names) - note.to_json(include: :tags) - else - status 400 - { error: 'There was a problem updating the note.', details: note.errors.full_messages }.to_json - end - end - - delete '/api/note/:id' do - content_type :json - note = current_user.notes.find_by(id: params[:id]) - halt 404, { error: 'Note not found.' }.to_json unless note - - if note.destroy - { message: 'Note deleted successfully.' }.to_json - else - status 400 - { error: 'There was a problem deleting the note.' }.to_json - end - end -end diff --git a/app/routes/projects_routes.rb b/app/routes/projects_routes.rb deleted file mode 100644 index 3a53f76..0000000 --- a/app/routes/projects_routes.rb +++ /dev/null @@ -1,136 +0,0 @@ -require 'sinatra/namespace' - -class Sinatra::Application - register Sinatra::Namespace - - def update_project_tags(project, tags_data) - return if tags_data.nil? - - tag_names = tags_data.map { |tag| tag['name'] }.compact.reject(&:empty?).uniq - - existing_tags = Tag.where(user: current_user, name: tag_names) - new_tags = tag_names - existing_tags.pluck(:name) - created_tags = new_tags.map { |name| Tag.create(name: name, user: current_user) } - - project.tags = (existing_tags + created_tags).uniq - end - - namespace '/api' do - before do - content_type :json - end - - get '/projects' do - active_param = params[:active] - is_active = active_param == 'true' unless active_param.nil? || active_param == 'all' - - pin_to_sidebar_param = params[:pin_to_sidebar] - is_pinned = pin_to_sidebar_param == 'true' unless pin_to_sidebar_param.nil? - - area_id_param = params[:area_id] - - projects = current_user.projects - .includes(:tags) - .left_joins(:tasks, :area) - .distinct - .order('projects.name ASC') - - projects = projects.where(active: is_active) unless is_active.nil? - projects = projects.where(pin_to_sidebar: is_pinned) unless is_pinned.nil? - projects = projects.where(area_id: area_id_param) unless area_id_param.blank? - task_status_counts = projects.each_with_object({}) do |project, counts| - counts[project.id] = project.task_status_counts - end - - grouped_projects = projects.group_by(&:area) - - { - projects: projects.as_json(include: { tasks: {}, area: { only: :name }, tags: { only: %i[id name] } }), - task_status_counts: task_status_counts, - grouped_projects: grouped_projects.as_json(include: { area: { only: :name } }) - }.to_json - end - - get '/project/:id' do - project = current_user.projects.includes(:tasks, :tags).find_by(id: params[:id]) - - halt 404, { error: 'Project not found' }.to_json unless project - - project.as_json(include: { tasks: {}, area: { only: %i[id name] }, tags: { only: %i[id name] } }).to_json - end - - post '/project' do - request_body = request.body.read - project_data = begin - JSON.parse(request_body) - rescue JSON::ParserError - halt 400, { error: 'Invalid JSON format.' }.to_json - end - - project_data['priority'] = Project.priorities[project_data['priority']] if project_data['priority'].is_a?(String) - - project = current_user.projects.new( - name: project_data['name'], - description: project_data['description'] || '', - area_id: project_data['area_id'], - active: true, - pin_to_sidebar: false, - priority: project_data['priority'], - due_date_at: project_data['due_date_at'] - ) - - if project.save - update_project_tags(project, project_data['tags']) - status 201 - project.as_json(include: { tags: { only: %i[id name] } }).to_json - else - status 400 - { error: 'There was a problem creating the project.', details: project.errors.full_messages }.to_json - end - end - - patch '/project/:id' do - project = current_user.projects.find_by(id: params[:id]) - - halt 404, { error: 'Project not found.' }.to_json unless project - - request_body = request.body.read - project_data = begin - JSON.parse(request_body) - rescue JSON::ParserError - halt 400, { error: 'Invalid JSON format.' }.to_json - end - - project.assign_attributes( - name: project_data['name'], - description: project_data['description'], - area_id: project_data['area_id'], - active: project_data['active'], - pin_to_sidebar: project_data['pin_to_sidebar'], - priority: project_data ['priority'], - due_date_at: project_data['due_date_at'] - ) - - if project.save - update_project_tags(project, project_data['tags']) - project.as_json(include: { tags: { only: %i[id name] } }).to_json - else - status 400 - { error: 'There was a problem updating the project.', details: project.errors.full_messages }.to_json - end - end - - delete '/project/:id' do - project = current_user.projects.find_by(id: params[:id]) - - halt 404, { error: 'Project not found' }.to_json unless project - - if project.destroy - { message: 'Project successfully deleted' }.to_json - else - status 400 - { error: 'There was a problem deleting the project.' }.to_json - end - end - end -end diff --git a/app/routes/tags_routes.rb b/app/routes/tags_routes.rb deleted file mode 100644 index 0ff656f..0000000 --- a/app/routes/tags_routes.rb +++ /dev/null @@ -1,67 +0,0 @@ -class Sinatra::Application - get '/api/tags' do - content_type :json - - tags = current_user.tags.order('name ASC') - - tags.as_json(only: %i[id name]).to_json - end - - get '/api/tag/:id' do - content_type :json - - tag = current_user.tags.find_by(id: params[:id]) - - halt 404, { error: 'Tag not found' }.to_json unless tag - - tag.as_json(only: %i[id name]).to_json - end - - post '/api/tag' do - content_type :json - - request_body = JSON.parse(request.body.read) - tag = current_user.tags.new(name: request_body['name']) - - if tag.save - status 201 - tag.as_json(only: %i[id name]).to_json - else - status 400 - { error: 'There was a problem creating the tag.' }.to_json - end - end - - patch '/api/tag/:id' do - content_type :json - - tag = current_user.tags.find_by(id: params[:id]) - - halt 404, { error: 'Tag not found' }.to_json unless tag - - request_body = JSON.parse(request.body.read) - tag.name = request_body['name'] - - if tag.save - tag.as_json(only: %i[id name]).to_json - else - status 400 - { error: 'There was a problem updating the tag.' }.to_json - end - end - - delete '/api/tag/:id' do - content_type :json - - tag = current_user.tags.find_by(id: params[:id]) - - halt 404, { error: 'Tag not found' }.to_json unless tag - - if tag.destroy - { message: 'Tag successfully deleted' }.to_json - else - status 400 - { error: 'There was a problem deleting the tag.' }.to_json - end - end -end diff --git a/app/routes/tasks_routes.rb b/app/routes/tasks_routes.rb deleted file mode 100644 index 3e1d06c..0000000 --- a/app/routes/tasks_routes.rb +++ /dev/null @@ -1,159 +0,0 @@ -module Sinatra - class Application - def update_task_tags(task, tags_data) - return if tags_data.nil? - - tag_names = tags_data.map { |tag| tag['name'] }.compact.reject(&:empty?).uniq - - existing_tags = Tag.where(user: current_user, name: tag_names) - new_tags = tag_names - existing_tags.pluck(:name) - created_tags = new_tags.map { |name| Tag.create(name: name, user: current_user) } - - task.tags = (existing_tags + created_tags).uniq - end - - get '/api/tasks' do - content_type :json - - begin - tasks = Task.filter_by_params(params, current_user) - rescue ArgumentError => e - halt 400, { error: e.message }.to_json - end - - metrics = Task.compute_metrics(current_user) - - # Prepare the response - response = { - tasks: tasks.as_json(include: { tags: { only: %i[id name] }, project: { only: :name } }), - metrics: { - total_open_tasks: metrics[:total_open_tasks], - tasks_pending_over_month: metrics[:tasks_pending_over_month], - tasks_in_progress_count: metrics[:tasks_in_progress_count], - tasks_in_progress: metrics[:tasks_in_progress].as_json(include: { tags: { only: %i[id name] }, - project: { only: :name } }), - tasks_due_today: metrics[:tasks_due_today].as_json(include: { tags: { only: %i[id name] }, - project: { only: :name } }), - suggested_tasks: metrics[:suggested_tasks].as_json(include: { tags: { only: %i[id name] }, - project: { only: :name } }) - } - } - - response.to_json - end - - post '/api/task' do - content_type :json - - request_body = request.body.read - task_data = begin - JSON.parse(request_body) - rescue JSON::ParserError => e - halt 400, { error: 'Invalid JSON format.' }.to_json - end - - task_attributes = { - name: task_data['name'], - priority: task_data['priority'], - due_date: task_data['due_date'].presence, - status: task_data['status'] || Task.statuses[:not_started], - note: task_data['note'], - user_id: current_user.id - } - - value = task_data['project_id'] - task = if value.nil? || value.to_s.strip.empty? - current_user.tasks.build(task_attributes) - else - project = current_user.projects.find_by(id: value) - halt 400, { error: 'Invalid project.' }.to_json unless project - project.tasks.build(task_attributes) - end - - if task.save - update_task_tags(task, task_data['tags']) - status 201 - task.to_json(include: { tags: { only: :name }, project: { only: :name } }) - else - errors = task.errors.full_messages - halt 400, { error: 'There was a problem creating the task.', details: errors }.to_json - end - end - - patch '/api/task/:id' do - content_type :json - puts "Request to update task with ID: #{params[:id]}" - puts "Current user: #{current_user&.id}" - - request_body = request.body.read - task_data = begin - JSON.parse(request_body) - rescue JSON::ParserError => e - halt 400, { error: 'Invalid JSON format.' }.to_json - end - - task = current_user.tasks.find_by(id: params[:id]) - - halt 404, { error: 'Task not found.' }.to_json unless task - - task_attributes = { - name: task_data['name'], # Get the name from the JSON body - priority: task_data['priority'], - status: task_data['status'] || Task.statuses[:not_started], - note: task_data['note'], - due_date: task_data['due_date'].presence - } - - if task_data['project_id'] && !task_data['project_id'].to_s.strip.empty? - project = current_user.projects.find_by(id: task_data['project_id']) - halt 400, { error: 'Invalid project.' }.to_json unless project - task.project = project - else - task.project = nil - end - - if task.update(task_attributes) - update_task_tags(task, task_data['tags']) - task.to_json(include: { tags: { only: :name }, project: { only: :name } }) - else - errors = task.errors.full_messages - halt 400, { error: 'There was a problem updating the task.', details: errors }.to_json - end - end - - patch '/api/task/:id/toggle_completion' do - content_type :json - - task = current_user.tasks.find_by(id: params[:id]) - halt 404, { error: 'Task not found.' }.to_json unless task - - new_status = if task.done? - task.note.present? ? :in_progress : :not_started - else - :done - end - task.status = new_status - - if task.save - task.to_json - else - status 422 - { error: 'Unable to update task' }.to_json - end - end - - delete '/api/task/:id' do - content_type :json - - task = current_user.tasks.find_by(id: params[:id]) - halt 404, { error: 'Task not found.' }.to_json unless task - - if task.destroy - status 200 - { message: 'Task successfully deleted' }.to_json - else - halt 400, { error: 'There was a problem deleting the task.' }.to_json - end - end - end -end diff --git a/app/routes/telegram_poller.rb b/app/routes/telegram_poller.rb deleted file mode 100644 index decaf1a..0000000 --- a/app/routes/telegram_poller.rb +++ /dev/null @@ -1,231 +0,0 @@ -require 'net/http' -require 'uri' -require 'json' -require 'thread' - -# A class to handle polling for Telegram updates -class TelegramPoller - @@instance = nil - @@mutex = Mutex.new - - attr_reader :running, :thread, :poll_interval, :last_update_id, :users_to_poll - - def initialize - @running = false - @thread = nil - @poll_interval = 5 # seconds - @last_update_id = 0 - @users_to_poll = [] - - # Keep a record of which users have active polling - @user_status = {} - end - - def self.instance - @@mutex.synchronize do - @@instance ||= new - end - @@instance - end - - # Start polling for a specific user - def add_user(user) - return false unless user && user.telegram_bot_token - - @users_to_poll << user unless @users_to_poll.any? { |u| u.id == user.id } - - # Start the polling thread if not already running - start_polling if @users_to_poll.any? && !@running - - true - end - - # Remove a user from polling - def remove_user(user_id) - @users_to_poll.reject! { |u| u.id == user_id } - - # Stop polling if no users left - stop_polling if @users_to_poll.empty? && @running - - true - end - - # Start the polling thread - def start_polling - return if @running - - @running = true - @thread = Thread.new do - while @running - begin - poll_updates - rescue => e - puts "Error polling Telegram: #{e.message}" - puts e.backtrace.join("\n") - end - - sleep @poll_interval - end - end - end - - # Stop the polling thread - def stop_polling - return unless @running - - @running = false - @thread.join if @thread - @thread = nil - end - - # Poll for updates from Telegram - def poll_updates - @users_to_poll.each do |user| - token = user.telegram_bot_token - next unless token - - begin - # Get updates from Telegram - uri = URI.parse("https://api.telegram.org/bot#{token}/getUpdates") - - params = { - offset: @user_status[user.id]&.dig(:last_update_id).to_i + 1, - timeout: 1 # Short timeout for quick polling - } - - uri.query = URI.encode_www_form(params) - - http = Net::HTTP.new(uri.host, uri.port) - http.use_ssl = true - http.read_timeout = 5 - - request = Net::HTTP::Get.new(uri.request_uri) - response = http.request(request) - - if response.code == '200' - data = JSON.parse(response.body) - - if data['ok'] && data['result'].is_a?(Array) - process_updates(user, data['result']) - end - else - puts "Error polling Telegram for user #{user.id}: #{response.code} #{response.message}" - end - rescue => e - puts "Error getting updates for user #{user.id}: #{e.message}" - end - end - end - - # Process updates received from Telegram - def process_updates(user, updates) - return if updates.empty? - - # Track the highest update_id to avoid processing the same update twice - highest_update_id = updates.map { |u| u['update_id'].to_i }.max || 0 - - # Save the last update ID for this user - @user_status[user.id] ||= {} - @user_status[user.id][:last_update_id] = highest_update_id if highest_update_id > (@user_status[user.id][:last_update_id] || 0) - - updates.each do |update| - begin - # Process message updates - if update['message'] && update['message']['text'] - process_message(user, update) - end - rescue => e - puts "Error processing update #{update['update_id']}: #{e.message}" - end - end - end - - # Process a single message - def process_message(user, update) - message = update['message'] - text = message['text'] - chat_id = message['chat']['id'].to_s - message_id = message['message_id'] - - puts "Processing message from user #{user.id}: #{text}" - - # Save the chat_id if not already saved - if user.telegram_chat_id.nil? || user.telegram_chat_id.empty? - puts "Updating user's telegram_chat_id to #{chat_id}" - user.update(telegram_chat_id: chat_id) - end - - # Create an inbox item - inbox_item = user.inbox_items.build( - content: text, - source: 'telegram' - ) - - if inbox_item.save - puts "Created inbox item #{inbox_item.id} from Telegram message" - - # Send confirmation - begin - send_telegram_message( - user.telegram_bot_token, - chat_id, - "✅ Added to Tududi inbox: \"#{text}\"", - message_id - ) - rescue => e - puts "Error sending confirmation: #{e.message}" - end - else - puts "Failed to create inbox item: #{inbox_item.errors.full_messages.join(', ')}" - - # Send error message - begin - send_telegram_message( - user.telegram_bot_token, - chat_id, - "❌ Failed to add to inbox: #{inbox_item.errors.full_messages.join(', ')}", - message_id - ) - rescue => e - puts "Error sending error message: #{e.message}" - end - end - end - - # Send a message to Telegram - def send_telegram_message(token, chat_id, text, reply_to_message_id = nil) - uri = URI.parse("https://api.telegram.org/bot#{token}/sendMessage") - - # Prepare message parameters - message_params = { - chat_id: chat_id, - text: text, - parse_mode: "MarkdownV2" - } - - # Add reply_to_message_id if provided - message_params[:reply_to_message_id] = reply_to_message_id if reply_to_message_id - - # Send the request to Telegram API - http = Net::HTTP.new(uri.host, uri.port) - http.use_ssl = true - request = Net::HTTP::Post.new(uri.request_uri, 'Content-Type' => 'application/json') - request.body = message_params.to_json - - response = http.request(request) - return JSON.parse(response.body) - end - - # Get status of the poller - def status - { - running: @running, - users_count: @users_to_poll.size, - poll_interval: @poll_interval, - user_status: @user_status - } - end -end - -# Initialize the poller when this file is loaded -TelegramPoller.instance \ No newline at end of file diff --git a/app/routes/telegram_routes.rb b/app/routes/telegram_routes.rb deleted file mode 100644 index 791e446..0000000 --- a/app/routes/telegram_routes.rb +++ /dev/null @@ -1,160 +0,0 @@ -require 'net/http' -require 'uri' -require 'json' -require_relative 'telegram_poller' - -module Sinatra - class Application - # Start polling for a user - post '/api/telegram/start-polling' do - content_type :json - - # Get the current user's Telegram token - user = current_user - halt 400, { error: 'Telegram bot token not set.' }.to_json unless user.telegram_bot_token - - # Add the user to the polling list - if TelegramPoller.instance.add_user(user) - { - success: true, - message: 'Telegram polling started', - status: TelegramPoller.instance.status - }.to_json - else - halt 500, { error: 'Failed to start Telegram polling.' }.to_json - end - end - - # Stop polling for a user - post '/api/telegram/stop-polling' do - content_type :json - - user = current_user - - # Remove the user from the polling list - if TelegramPoller.instance.remove_user(user.id) - { - success: true, - message: 'Telegram polling stopped', - status: TelegramPoller.instance.status - }.to_json - else - halt 500, { error: 'Failed to stop Telegram polling.' }.to_json - end - end - - # Get polling status - get '/api/telegram/polling-status' do - content_type :json - - { - success: true, - status: TelegramPoller.instance.status, - is_polling: TelegramPoller.instance.users_to_poll.any? { |u| u.id == current_user.id } - }.to_json - end - - # Setup the Telegram bot for a user (save token and start polling) - post '/api/telegram/setup' do - content_type :json - request_body = request.body.read - - begin - setup_data = JSON.parse(request_body) - rescue JSON::ParserError - halt 400, { error: 'Invalid JSON format.' }.to_json - end - - token = setup_data['token'] - halt 400, { error: 'Telegram bot token is required.' }.to_json unless token && !token.empty? - - # Validate the token by making a getMe request to Telegram - begin - uri = URI.parse("https://api.telegram.org/bot#{token}/getMe") - http = Net::HTTP.new(uri.host, uri.port) - http.use_ssl = true - - response = http.get(uri.request_uri) - json_response = JSON.parse(response.body) - - if json_response['ok'] - # Token is valid, save it to the user - bot_username = json_response['result']['username'] - current_user.update(telegram_bot_token: token) - - # Start polling for this user - TelegramPoller.instance.add_user(current_user) - - # Return success with bot info - { - success: true, - message: 'Telegram bot configured successfully and polling started!', - bot: { - username: bot_username, - polling_status: TelegramPoller.instance.status, - chat_url: "https://t.me/#{bot_username}" - } - }.to_json - else - halt 400, { error: 'Invalid Telegram bot token.', details: json_response['description'] }.to_json - end - rescue => e - halt 500, { error: 'Error validating Telegram bot token.', details: e.message }.to_json - end - end - - # Test endpoint to simulate a Telegram message (for development) - post '/api/telegram/test/:user_id' do - content_type :json - request_body = request.body.read - - begin - message_data = JSON.parse(request_body) - rescue JSON::ParserError - halt 400, { error: 'Invalid JSON format.' }.to_json - end - - user_id = params[:user_id] - user = User.find_by(id: user_id) - halt 404, { error: 'User not found.' }.to_json unless user - halt 400, { error: 'User has no Telegram bot token configured.' }.to_json unless user.telegram_bot_token - - text = message_data['text'] || 'Test message from development environment' - - # Create an inbox item directly - inbox_item = user.inbox_items.build( - content: text, - source: 'telegram' - ) - - if inbox_item.save - # Send confirmation to Telegram if the user has a chat_id - if user.telegram_chat_id - begin - # Use the TelegramPoller's send_message method - response = TelegramPoller.instance.send_telegram_message( - user.telegram_bot_token, - user.telegram_chat_id, - "✅ Added to Tududi inbox: \"#{text}\"" - ) - puts "Test message confirmation sent: #{response}" - rescue => e - puts "Error sending test confirmation: #{e.message}" - end - end - - { - success: true, - message: 'Test Telegram message processed successfully!', - inbox_item_id: inbox_item.id - }.to_json - else - { - success: false, - message: 'Failed to create inbox item from test message', - errors: inbox_item.errors.full_messages - }.to_json - end - end - end -end \ No newline at end of file diff --git a/app/routes/url_routes.rb b/app/routes/url_routes.rb deleted file mode 100644 index aa71605..0000000 --- a/app/routes/url_routes.rb +++ /dev/null @@ -1,43 +0,0 @@ -require_relative '../services/url_title_extractor_service' - -module Sinatra - class Application - get '/api/url/title' do - content_type :json - - url = params[:url] - halt 400, { error: 'URL parameter is required' }.to_json unless url - - title = UrlTitleExtractorService.extract_title(url) - - if title - { url: url, title: title }.to_json - else - { url: url, title: nil, error: 'Could not extract title' }.to_json - end - end - - post '/api/url/extract-from-text' do - content_type :json - - request_body = request.body.read - - begin - data = JSON.parse(request_body) - text = data['text'] - - halt 400, { error: 'Text parameter is required' }.to_json unless text - - result = UrlTitleExtractorService.extract_title_from_text(text) - - if result - result.to_json - else - { found: false }.to_json - end - rescue JSON::ParserError - halt 400, { error: 'Invalid JSON format' }.to_json - end - end - end -end diff --git a/app/routes/users_routes.rb b/app/routes/users_routes.rb deleted file mode 100644 index 9d0bc9f..0000000 --- a/app/routes/users_routes.rb +++ /dev/null @@ -1,168 +0,0 @@ -module Sinatra - class Application - get '/api/profile' do - content_type :json - user = current_user - - if user - user.to_json(only: %i[id email appearance language timezone avatar_image telegram_bot_token telegram_chat_id task_summary_enabled task_summary_frequency]) - else - halt 404, { error: 'Profile not found.' }.to_json - end - end - - patch '/api/profile' do - content_type :json - - begin - request_payload = JSON.parse(request.body.read) - rescue JSON::ParserError - halt 400, { error: 'Invalid JSON format.' }.to_json - end - - user = current_user - - halt 404, { error: 'Profile not found.' }.to_json if user.nil? - - allowed_params = {} - allowed_params[:appearance] = request_payload['appearance'] if request_payload.key?('appearance') - allowed_params[:language] = request_payload['language'] if request_payload.key?('language') - allowed_params[:timezone] = request_payload['timezone'] if request_payload.key?('timezone') - allowed_params[:avatar_image] = request_payload['avatar_image'] if request_payload.key?('avatar_image') - allowed_params[:telegram_bot_token] = request_payload['telegram_bot_token'] if request_payload.key?('telegram_bot_token') - - if user.update(allowed_params) - user.to_json(only: %i[id email appearance language timezone avatar_image telegram_bot_token telegram_chat_id]) - else - status 400 - { error: 'Failed to update profile.', details: user.errors.full_messages }.to_json - end - end - - post '/api/profile/task-summary/toggle' do - content_type :json - - user = current_user - halt 404, { error: 'User not found.' }.to_json unless user - - # Toggle the task_summary_enabled flag - enabled = !user.task_summary_enabled - - if user.update(task_summary_enabled: enabled) - # If enabling, send a test summary to confirm it works - if enabled && user.telegram_bot_token && user.telegram_chat_id - begin - success = TaskSummaryService.send_summary_to_user(user.id) - - if success - { - success: true, - enabled: enabled, - message: 'Task summary notifications have been enabled and a test message was sent to your Telegram.' - }.to_json - else - user.update(task_summary_enabled: false) - halt 400, { - error: 'Failed to send test message to Telegram. Please check your Telegram bot configuration.' - }.to_json - end - rescue => e - user.update(task_summary_enabled: false) - halt 400, { - error: 'Error sending test message to Telegram.', - details: e.message - }.to_json - end - else - { - success: true, - enabled: enabled, - message: enabled ? 'Task summary notifications have been enabled.' : 'Task summary notifications have been disabled.' - }.to_json - end - else - halt 400, { - error: 'Failed to update task summary settings.', - details: user.errors.full_messages - }.to_json - end - end - - post '/api/profile/task-summary/frequency' do - content_type :json - - begin - request_payload = JSON.parse(request.body.read) - rescue JSON::ParserError - halt 400, { error: 'Invalid JSON format.' }.to_json - end - - frequency = request_payload['frequency'] - halt 400, { error: 'Frequency is required.' }.to_json unless frequency - - # Validate frequency value - valid_frequencies = User::TASK_SUMMARY_FREQUENCIES - halt 400, { error: 'Invalid frequency value.' }.to_json unless valid_frequencies.include?(frequency) - - user = current_user - halt 404, { error: 'User not found.' }.to_json unless user - - if user.update(task_summary_frequency: frequency) - { - success: true, - frequency: frequency, - message: "Task summary frequency has been set to #{frequency}." - }.to_json - else - halt 400, { - error: 'Failed to update task summary frequency.', - details: user.errors.full_messages - }.to_json - end - end - - post '/api/profile/task-summary/send-now' do - content_type :json - - user = current_user - halt 404, { error: 'User not found.' }.to_json unless user - - if user.telegram_bot_token && user.telegram_chat_id - begin - success = TaskSummaryService.send_summary_to_user(user.id) - - if success - { - success: true, - message: 'Task summary was sent to your Telegram.' - }.to_json - else - halt 400, { error: 'Failed to send message to Telegram.' }.to_json - end - rescue => e - halt 400, { - error: 'Error sending message to Telegram.', - details: e.message - }.to_json - end - else - halt 400, { error: 'Telegram bot is not properly configured.' }.to_json - end - end - - get '/api/profile/task-summary/status' do - content_type :json - - user = current_user - halt 404, { error: 'User not found.' }.to_json unless user - - { - success: true, - enabled: user.task_summary_enabled, - frequency: user.task_summary_frequency, - last_run: user.task_summary_last_run, - next_run: user.task_summary_next_run - }.to_json - end - end -end diff --git a/app/services/task_summary_service.rb b/app/services/task_summary_service.rb deleted file mode 100644 index 994ee1a..0000000 --- a/app/services/task_summary_service.rb +++ /dev/null @@ -1,288 +0,0 @@ -# app/services/task_summary_service.rb -require 'yaml' - -class TaskSummaryService - # Helper method to escape special characters for MarkdownV2 - def self.escape_markdown(text) - # Characters that need to be escaped in MarkdownV2: _*[]()~`>#+-=|{}.! - text.to_s.gsub(/([_*\[\]()~`>#+\-=|{}.!])/, '\\\\\1') - end - - def self.generate_summary_for_user(user_id) - user = User.find_by(id: user_id) - return nil unless user - - # Get today's tasks, in progress tasks, etc. - tasks = user.tasks - - today = Date.today - due_today = tasks.where('DATE(due_date) = ?', today).where.not(status: 'done') - in_progress = tasks.where(status: 'in_progress') - completed_today = tasks.where(status: 'done').where('DATE(updated_at) = ?', today) - - # Generate summary message - message = "📋 *Today's Task Summary*\n\n" - - # Add a header divider - message += "━━━━━━━━━━━━━━━━━━━━━━━━\n\n" - - # Start Today's Plan section - message += "✏️ *Today's Plan*\n\n" - - # Add due today tasks to Today's Plan - # Add due today tasks to Today's Plan - if due_today.any? - message += "🚀 *Tasks Due Today:*\n" - due_today.order(:name).each_with_index do |task, index| - priority_emoji = - case task.priority - when 'high' then '🔴' - when 'medium' then '🟠' - when 'low' then '🟢' - else '⚪' - end - - # Escape special characters in task name and project name - task_name = escape_markdown(task.name) - project_info = task.project ? " \\[#{escape_markdown(task.project.name)}\\]" : '' - - message += "#{index + 1}\\. #{priority_emoji} #{task_name}#{project_info}\n" - end - message += "\n" - end - # Add in progress tasks to Today's Plan - if in_progress.any? - message += "⚙️ *In Progress Tasks:*\n" - in_progress.order(:name).each_with_index do |task, index| - priority_emoji = - case task.priority - when 'high' then '🔴' - when 'medium' then '🟠' - when 'low' then '🟢' - else '⚪' - end - - # Escape special characters in task name and project name - task_name = escape_markdown(task.name) - project_info = task.project ? " \\[#{escape_markdown(task.project.name)}\\]" : '' - - message += "#{index + 1}\\. #{priority_emoji} #{task_name}#{project_info}\n" - end - message += "\n" - end - # Add suggested tasks (not done, not in due today or in progress) - suggested_task_ids = due_today.pluck(:id) + in_progress.pluck(:id) - - # Get tasks in expiring projects - same logic as Task.compute_metrics - tasks_in_expiring_projects = tasks - .where.not(status: 'done') - .where.not(id: suggested_task_ids) - .joins(:project) - .where('projects.due_date_at >= ?', today) - .where(projects: { active: true }) # Only active projects - .order(Arel.sql('projects.due_date_at ASC, tasks.priority DESC')) - - # Get tasks not assigned to projects - same logic as Task.compute_metrics - tasks_without_projects = tasks - .where.not(status: 'done') - .where.not(id: suggested_task_ids) - .where(project_id: nil, status: 'not_started') - .order(priority: :desc) - - # Combine both sets of tasks - combined_tasks = (tasks_in_expiring_projects + tasks_without_projects) - - # Sort using same logic as Task.sort_suggested_tasks - suggested_tasks = combined_tasks.sort_by do |task| - # Parse or default the task due date - task_due_date = if task.due_date.is_a?(String) - Date.parse(task.due_date) - else - task.due_date || Date.new(9999, 12, 31) - end - - # Parse or default the project due date - project_due_date = if task.project&.due_date_at.is_a?(String) - Date.parse(task&.project&.due_date_at) - else - task.project&.due_date_at || Date.new(9999, 12, 31) - end - - # Priority in descending order (sorted values should be negative for sort_by) - priority_value = -Task.priorities.fetch(task.priority, -1) - - # Determine sorting flags based on various criteria - is_high_priority_proj_with_due_date = task.priority == 'high' && task.project&.due_date_at ? 0 : 1 - is_high_priority_with_due_date = task.priority == 'high' && task.due_date ? 0 : 1 - is_high_priority = task.priority == 'high' && !task.due_date && !task.project&.due_date_at ? 0 : 1 - - is_medium_priority_proj_with_due_date = task.priority == 'medium' && task.project&.due_date_at ? 0 : 1 - is_medium_priority_with_due_date = task.priority == 'medium' && task.due_date ? 0 : 1 - is_medium_priority = task.priority == 'medium' && !task.due_date && !task.project&.due_date_at ? 0 : 1 - - is_low_priority_proj_with_due_date = task.priority == 'low' && task.project&.due_date_at ? 0 : 1 - is_low_priority_with_due_date = task.priority == 'low' && task.due_date ? 0 : 1 - is_low_priority = task.priority == 'low' && !task.due_date && !task.project&.due_date_at ? 0 : 1 - - # Primary sorting criteria - same as Task.sort_suggested_tasks - [ - is_high_priority_proj_with_due_date, - is_high_priority_with_due_date, - is_high_priority, - - is_medium_priority_proj_with_due_date, - is_medium_priority_with_due_date, - is_medium_priority, - - is_low_priority_proj_with_due_date, - is_low_priority_with_due_date, - is_low_priority, - - task_due_date, - project_due_date, - priority_value - ] - end.first(5) - - if suggested_tasks.any? - message += "💡 *Suggested Tasks \\(Top 3\\):*\n" - # Only display the top 3 suggested tasks - suggested_tasks.first(5).each_with_index do |task, index| - priority_emoji = - case task.priority - when 'high' then '🔴' - when 'medium' then '🟠' - when 'low' then '🟢' - else '⚪' - end - - # Escape special characters in task name and project name - task_name = escape_markdown(task.name) - project_info = task.project ? " \\[#{escape_markdown(task.project.name)}\\]" : '' - due_date = task.due_date ? " \\(Due: #{escape_markdown(task.due_date.strftime('%b %d'))}\\)" : '' - - message += "#{index + 1}\\. #{priority_emoji} #{task_name}#{project_info}#{due_date}\n" - end - message += "\n" - end - - # Add a section divider - message += "━━━━━━━━━━━━━━━━━━━━━━━━\n\n" - - # Add completed tasks for today if any - if completed_today.any? - message += "✅ *Completed Today:*\n" - completed_today.order(updated_at: :desc).each_with_index do |task, index| - # Escape special characters in task name and project name - task_name = escape_markdown(task.name) - project_info = task.project ? " \\[#{escape_markdown(task.project.name)}\\]" : '' - - message += "#{index + 1}\\. #{task_name}#{project_info}\n" - end - message += "\n" - end - - # Add inbox count if available - inbox_items_count = user.inbox_items.where(status: 'added').count - if inbox_items_count > 0 - message += "*Inbox:*\n" - message += "• You have #{inbox_items_count} item\\(s\\) in your inbox to process\\.\n\n" - end - - # Add a section divider - message += "━━━━━━━━━━━━━━━━━━━━━━━━\n\n" - # Add a motivational note from the YAML file - begin - quotes_file = Rails.root.join('config', 'quotes.yml') - quotes_data = YAML.load_file(quotes_file)['quotes'] - - message += "💪 *Today's Motivation:*\n" - quote = quotes_data.sample - # Escape special characters in the quote - message += escape_markdown(quote) - rescue StandardError => e - # Fallback to default quotes if there's an issue loading from YAML - default_quotes = [ - 'Focus on progress, not perfection.', - 'One task at a time leads to great accomplishments.', - "Today's effort is tomorrow's success.", - 'Small steps every day lead to big results.' - ] - - message += "💪 *Today's Motivation:*\n" - quote = default_quotes.sample - # Escape special characters in the quote - message += escape_markdown(quote) - end - - message - end - - def self.send_summary_to_user(user_id) - user = User.find_by(id: user_id) - return false unless user && user.telegram_bot_token && user.telegram_chat_id - - summary = generate_summary_for_user(user_id) - return false unless summary - - # Send the message via Telegram - begin - TelegramPoller.instance.send_telegram_message( - user.telegram_bot_token, - user.telegram_chat_id, - summary - ) - - # Update the last run time and calculate the next run time - now = Time.now - next_run = calculate_next_run_time(user, now) - - # Update the user's tracking fields - user.update( - task_summary_last_run: now, - task_summary_next_run: next_run - ) - - true - rescue StandardError => e - puts "Error sending task summary to user #{user_id}: #{e.message}" - false - end - end - - # Calculate when the next task summary should run based on frequency - def self.calculate_next_run_time(user, from_time = Time.now) - case user.task_summary_frequency - when 'daily' - # Next day at 7 AM - from_time.tomorrow.change(hour: 7, min: 0, sec: 0) - when 'weekdays' - # If it's Friday, next is Monday, otherwise next day (if it's a weekday) - days_until_next_weekday = - if from_time.wday == 5 # Friday - 3 # Next Monday - elsif from_time.wday == 6 # Saturday - 2 # Next Monday - else - 1 # Next day - end - from_time.advance(days: days_until_next_weekday).change(hour: 7, min: 0, sec: 0) - when 'weekly' - # Next week same day, or next Monday if we're being specific - from_time.advance(days: 7).change(hour: 7, min: 0, sec: 0) - when '1h' - from_time + 1.hour - when '2h' - from_time + 2.hours - when '4h' - from_time + 4.hours - when '8h' - from_time + 8.hours - when '12h' - from_time + 12.hours - else - # Default to daily at 7 AM - from_time.tomorrow.change(hour: 7, min: 0, sec: 0) - end - end -end diff --git a/app/services/url_title_extractor_service.rb b/app/services/url_title_extractor_service.rb deleted file mode 100644 index 244a902..0000000 --- a/app/services/url_title_extractor_service.rb +++ /dev/null @@ -1,71 +0,0 @@ -require 'net/http' -require 'uri' -require 'nokogiri' - -class UrlTitleExtractorService - MAX_BYTES = 50_000 - TIMEOUT = 5 - USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' - - def self.url?(text) - url_regex = %r{^(https?://)?[a-z0-9]+([-.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(/.*)?$}i - text.strip.match?(url_regex) - end - - def self.extract_title(url) - url = "http://#{url}" unless url.start_with?('http://') || url.start_with?('https://') - - begin - uri = URI.parse(url) - http = Net::HTTP.new(uri.host, uri.port) - - http.open_timeout = TIMEOUT - http.read_timeout = TIMEOUT - - if uri.scheme == 'https' - http.use_ssl = true - http.verify_mode = OpenSSL::SSL::VERIFY_NONE - end - - request = Net::HTTP::Get.new(uri.request_uri) - request['User-Agent'] = USER_AGENT - request['Accept'] = 'text/html' - request['Range'] = "bytes=0-#{MAX_BYTES}" - - response = http.request(request) - - if response.is_a?(Net::HTTPRedirection) - redirect_url = response['location'] - return extract_title(redirect_url) - end - - if response.code.to_i.between?(200, 299) && response.body - html = Nokogiri::HTML(response.body) - - title = html.at_css('title')&.text&.strip - return title if title && !title.empty? - - og_title = html.at_css('meta[property="og:title"]')&.attributes&.[]('content')&.value&.strip - return og_title if og_title && !og_title.empty? - - twitter_title = html.at_css('meta[name="twitter:title"]')&.attributes&.[]('content')&.value&.strip - return twitter_title if twitter_title && !twitter_title.empty? - end - - nil - rescue StandardError => e - puts "Error extracting title from URL: #{e.message}" - nil - end - end - - def self.extract_title_from_text(text) - text.split(/\s+/).each do |word| - if url?(word) - title = extract_title(word) - return { url: word, title: title } if title - end - end - nil - end -end diff --git a/app/views/index.erb b/app/views/index.erb deleted file mode 100644 index 93f8214..0000000 --- a/app/views/index.erb +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - Tududi - - -
- - diff --git a/app/views/layout.erb b/app/views/layout.erb deleted file mode 100644 index 33a4622..0000000 --- a/app/views/layout.erb +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - Tududi - - - <%= yield %> - - diff --git a/backend/.env.test b/backend/.env.test new file mode 100644 index 0000000..b1bf7e1 --- /dev/null +++ b/backend/.env.test @@ -0,0 +1,4 @@ +# Test environment configuration +NODE_ENV=test +TUDUDI_SESSION_SECRET=test-secret-key-for-testing +TUDUDI_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:8080 \ No newline at end of file diff --git a/backend/.sequelizerc b/backend/.sequelizerc new file mode 100644 index 0000000..683bb52 --- /dev/null +++ b/backend/.sequelizerc @@ -0,0 +1,8 @@ +const path = require('path'); + +module.exports = { + 'config': path.resolve('config', 'database.js'), + 'models-path': path.resolve('models'), + 'seeders-path': path.resolve('seeders'), + 'migrations-path': path.resolve('migrations') +}; \ No newline at end of file diff --git a/backend/app.js b/backend/app.js new file mode 100644 index 0000000..5657f4f --- /dev/null +++ b/backend/app.js @@ -0,0 +1,167 @@ +require('dotenv').config(); +const express = require('express'); +const path = require('path'); +const cors = require('cors'); +const helmet = require('helmet'); +const compression = require('compression'); +const morgan = require('morgan'); +const session = require('express-session'); +const SequelizeStore = require('connect-session-sequelize')(session.Store); +const { sequelize } = require('./models'); +const { initializeTelegramPolling } = require('./services/telegramInitializer'); +const TaskScheduler = require('./services/taskScheduler'); + +const app = express(); + +// Session store +const sessionStore = new SequelizeStore({ + db: sequelize, +}); + +// Middlewares +app.use(helmet()); +app.use(compression()); +app.use(morgan('combined')); + +// CORS configuration +const allowedOrigins = process.env.TUDUDI_ALLOWED_ORIGINS + ? process.env.TUDUDI_ALLOWED_ORIGINS.split(',').map(origin => origin.trim()) + : ['http://localhost:8080', 'http://localhost:9292', 'http://127.0.0.1:8080', 'http://127.0.0.1:9292']; + +app.use(cors({ + origin: allowedOrigins, + credentials: true, + methods: ['GET', 'POST', 'PATCH', 'DELETE', 'OPTIONS'], + allowedHeaders: ['Authorization', 'Content-Type', 'Accept', 'X-Requested-With'], + exposedHeaders: ['Content-Type'], + maxAge: 1728000 +})); + +// Body parsing +app.use(express.json({ limit: '10mb' })); +app.use(express.urlencoded({ extended: true, limit: '10mb' })); + +// Session configuration +const secureFlag = process.env.NODE_ENV === 'production' && process.env.TUDUDI_INTERNAL_SSL_ENABLED === 'true'; +app.use(session({ + secret: process.env.TUDUDI_SESSION_SECRET || require('crypto').randomBytes(64).toString('hex'), + store: sessionStore, + resave: false, + saveUninitialized: false, + cookie: { + httpOnly: true, + secure: secureFlag, + maxAge: 2592000000, // 30 days + sameSite: secureFlag ? 'none' : 'lax' + } +})); + +// Static files +if (process.env.NODE_ENV === 'production') { + app.use(express.static(path.join(__dirname, 'dist'))); +} else { + app.use(express.static('public')); +} + +// Serve locales +if (process.env.NODE_ENV === 'production') { + app.use('/locales', express.static(path.join(__dirname, 'dist/locales'))); +} else { + app.use('/locales', express.static(path.join(__dirname, '../public/locales'))); +} + +// Authentication middleware +const { requireAuth } = require('./middleware/auth'); + +// Routes +app.use('/api', require('./routes/auth')); +app.use('/api', requireAuth, require('./routes/tasks')); +app.use('/api', requireAuth, require('./routes/projects')); +app.use('/api', requireAuth, require('./routes/areas')); +app.use('/api', requireAuth, require('./routes/notes')); +app.use('/api', requireAuth, require('./routes/tags')); +app.use('/api', requireAuth, require('./routes/users')); +app.use('/api', requireAuth, require('./routes/inbox')); +app.use('/api', requireAuth, require('./routes/url')); +app.use('/api', requireAuth, require('./routes/telegram')); +app.use('/api', requireAuth, require('./routes/quotes')); + +// Health check +app.get('/api/health', (req, res) => { + res.json({ status: 'ok', timestamp: new Date().toISOString() }); +}); + +// SPA fallback +app.get('*', (req, res) => { + if (!req.path.startsWith('/api/') && !req.path.match(/\.(js|css|png|jpg|jpeg|gif|ico|svg)$/)) { + if (process.env.NODE_ENV === 'production') { + res.sendFile(path.join(__dirname, 'dist', 'index.html')); + } else { + res.sendFile(path.join(__dirname, 'public', 'index.html')); + } + } else { + res.status(404).json({ error: 'Not Found', message: 'The requested resource could not be found.' }); + } +}); + +// Error handling +app.use((err, req, res, next) => { + console.error(err.stack); + res.status(500).json({ error: 'Internal Server Error', message: err.message }); +}); + +const PORT = process.env.PORT || 3002; + +// Initialize database and start server +async function startServer() { + try { + // Create session store table + await sessionStore.sync(); + + // Sync database + await sequelize.sync(); + + // Auto-create user if not exists + if (process.env.TUDUDI_USER_EMAIL && process.env.TUDUDI_USER_PASSWORD) { + const { User } = require('./models'); + const bcrypt = require('bcrypt'); + + const [user, created] = await User.findOrCreate({ + where: { email: process.env.TUDUDI_USER_EMAIL }, + defaults: { + email: process.env.TUDUDI_USER_EMAIL, + password: await bcrypt.hash(process.env.TUDUDI_USER_PASSWORD, 10) + } + }); + + if (created) { + console.log('Default user created:', user.email); + } + } + + // Initialize Telegram polling after database is ready + await initializeTelegramPolling(); + + // Initialize task scheduler + const scheduler = TaskScheduler.getInstance(); + await scheduler.initialize(); + + const server = app.listen(PORT, '0.0.0.0', () => { + console.log(`Server running on port ${PORT}`); + console.log(`Server listening on http://localhost:${PORT}`); + }); + + server.on('error', (err) => { + console.error('Server error:', err); + }); + } catch (error) { + console.error('Failed to start server:', error); + process.exit(1); + } +} + +if (require.main === module) { + startServer(); +} + +module.exports = app; \ No newline at end of file diff --git a/backend/config/database.js b/backend/config/database.js new file mode 100644 index 0000000..05afcff --- /dev/null +++ b/backend/config/database.js @@ -0,0 +1,42 @@ +require('dotenv').config(); +const path = require('path'); + +const dbPath = process.env.DATABASE_URL + ? process.env.DATABASE_URL.replace('sqlite:///', '') + : path.join(__dirname, '..', 'db'); + +module.exports = { + development: { + dialect: 'sqlite', + storage: path.join(dbPath, 'development.sqlite3'), + logging: console.log, + define: { + timestamps: true, + underscored: true, + createdAt: 'created_at', + updatedAt: 'updated_at' + } + }, + test: { + dialect: 'sqlite', + storage: path.join(dbPath, 'test.sqlite3'), + logging: false, + define: { + timestamps: true, + underscored: true, + createdAt: 'created_at', + updatedAt: 'updated_at' + } + }, + production: { + dialect: 'sqlite', + storage: path.join(dbPath, 'production.sqlite3'), + logging: false, + define: { + timestamps: true, + underscored: true, + createdAt: 'created_at', + updatedAt: 'updated_at' + } + } +}; \ No newline at end of file diff --git a/config/quotes.yml b/backend/config/quotes.yml similarity index 100% rename from config/quotes.yml rename to backend/config/quotes.yml diff --git a/backend/jest.config.js b/backend/jest.config.js new file mode 100644 index 0000000..839bcc6 --- /dev/null +++ b/backend/jest.config.js @@ -0,0 +1,25 @@ +module.exports = { + testEnvironment: 'node', + setupFilesAfterEnv: ['/tests/helpers/setup.js'], + testMatch: [ + '/tests/**/*.test.js', + '/tests/**/*.spec.js' + ], + maxWorkers: 1, + collectCoverageFrom: [ + 'routes/**/*.js', + 'models/**/*.js', + 'middleware/**/*.js', + 'services/**/*.js', + '!models/index.js', + '!**/*.test.js', + '!**/*.spec.js' + ], + coverageDirectory: 'coverage', + coverageReporters: ['text', 'lcov', 'html'], + verbose: true, + forceExit: true, + clearMocks: true, + resetMocks: true, + restoreMocks: true +}; \ No newline at end of file diff --git a/backend/middleware/auth.js b/backend/middleware/auth.js new file mode 100644 index 0000000..0b99144 --- /dev/null +++ b/backend/middleware/auth.js @@ -0,0 +1,30 @@ +const { User } = require('../models'); + +const requireAuth = async (req, res, next) => { + try { + // Skip authentication for health check, login routes, and current_user + if (req.path === '/api/health' || req.path === '/api/login' || req.path === '/api/current_user') { + return next(); + } + + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const user = await User.findByPk(req.session.userId); + if (!user) { + req.session.destroy(); + return res.status(401).json({ error: 'User not found' }); + } + + req.currentUser = user; + next(); + } catch (error) { + console.error('Authentication error:', error); + res.status(500).json({ error: 'Authentication error' }); + } +}; + +module.exports = { + requireAuth +}; \ No newline at end of file diff --git a/backend/migrations/20250615000001-create-users.js b/backend/migrations/20250615000001-create-users.js new file mode 100644 index 0000000..79cee6f --- /dev/null +++ b/backend/migrations/20250615000001-create-users.js @@ -0,0 +1,61 @@ +'use strict'; + +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable('users', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + email: { + type: Sequelize.STRING, + allowNull: false, + unique: true + }, + password: { + type: Sequelize.STRING, + allowNull: false + }, + telegram_bot_token: { + type: Sequelize.STRING, + allowNull: true + }, + telegram_chat_id: { + type: Sequelize.STRING, + allowNull: true + }, + task_summary_enabled: { + type: Sequelize.BOOLEAN, + defaultValue: false + }, + task_summary_frequency: { + type: Sequelize.STRING, + defaultValue: 'daily' + }, + task_summary_last_run: { + type: Sequelize.DATE, + allowNull: true + }, + task_summary_next_run: { + type: Sequelize.DATE, + allowNull: true + }, + created_at: { + allowNull: false, + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + } + }); + }, + + async down(queryInterface, Sequelize) { + await queryInterface.dropTable('users'); + } +}; \ No newline at end of file diff --git a/backend/models/area.js b/backend/models/area.js new file mode 100644 index 0000000..61bf11c --- /dev/null +++ b/backend/models/area.js @@ -0,0 +1,36 @@ +const { DataTypes } = require('sequelize'); + +module.exports = (sequelize) => { + const Area = sequelize.define('Area', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true + }, + name: { + type: DataTypes.STRING, + allowNull: false + }, + description: { + type: DataTypes.STRING, + allowNull: true + }, + user_id: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'users', + key: 'id' + } + } + }, { + tableName: 'areas', + indexes: [ + { + fields: ['user_id'] + } + ] + }); + + return Area; +}; \ No newline at end of file diff --git a/backend/models/inbox_item.js b/backend/models/inbox_item.js new file mode 100644 index 0000000..6bf854a --- /dev/null +++ b/backend/models/inbox_item.js @@ -0,0 +1,42 @@ +const { DataTypes } = require('sequelize'); + +module.exports = (sequelize) => { + const InboxItem = sequelize.define('InboxItem', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true + }, + content: { + type: DataTypes.STRING, + allowNull: false + }, + status: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: 'added' + }, + source: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: 'tududi' + }, + user_id: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'users', + key: 'id' + } + } + }, { + tableName: 'inbox_items', + indexes: [ + { + fields: ['user_id'] + } + ] + }); + + return InboxItem; +}; \ No newline at end of file diff --git a/backend/models/index.js b/backend/models/index.js new file mode 100644 index 0000000..005d36f --- /dev/null +++ b/backend/models/index.js @@ -0,0 +1,93 @@ +const { Sequelize } = require('sequelize'); +const path = require('path'); + +// Database configuration +let dbConfig; + +if (process.env.NODE_ENV === 'test') { + // Use in-memory database for tests + dbConfig = { + dialect: 'sqlite', + storage: ':memory:', + logging: false, + define: { + timestamps: true, + underscored: true, + createdAt: 'created_at', + updatedAt: 'updated_at' + } + }; +} else { + const dbPath = process.env.DATABASE_URL + ? process.env.DATABASE_URL.replace('sqlite:///', '') + : path.join(__dirname, '../db', process.env.NODE_ENV === 'production' ? 'production.sqlite3' : 'development.sqlite3'); + + dbConfig = { + dialect: 'sqlite', + storage: dbPath, + logging: process.env.NODE_ENV === 'development' ? console.log : false, + define: { + timestamps: true, + underscored: true, + createdAt: 'created_at', + updatedAt: 'updated_at' + } + }; +} + +const sequelize = new Sequelize(dbConfig); + +// Import models +const User = require('./user')(sequelize); +const Area = require('./area')(sequelize); +const Project = require('./project')(sequelize); +const Task = require('./task')(sequelize); +const Tag = require('./tag')(sequelize); +const Note = require('./note')(sequelize); +const InboxItem = require('./inbox_item')(sequelize); + +// Define associations +User.hasMany(Area, { foreignKey: 'user_id' }); +Area.belongsTo(User, { foreignKey: 'user_id' }); + +User.hasMany(Project, { foreignKey: 'user_id' }); +Project.belongsTo(User, { foreignKey: 'user_id' }); +Project.belongsTo(Area, { foreignKey: 'area_id', allowNull: true }); +Area.hasMany(Project, { foreignKey: 'area_id' }); + +User.hasMany(Task, { foreignKey: 'user_id' }); +Task.belongsTo(User, { foreignKey: 'user_id' }); +Task.belongsTo(Project, { foreignKey: 'project_id', allowNull: true }); +Project.hasMany(Task, { foreignKey: 'project_id' }); + +User.hasMany(Tag, { foreignKey: 'user_id' }); +Tag.belongsTo(User, { foreignKey: 'user_id' }); + +User.hasMany(Note, { foreignKey: 'user_id' }); +Note.belongsTo(User, { foreignKey: 'user_id' }); +Note.belongsTo(Project, { foreignKey: 'project_id', allowNull: true }); +Project.hasMany(Note, { foreignKey: 'project_id' }); + +User.hasMany(InboxItem, { foreignKey: 'user_id' }); +InboxItem.belongsTo(User, { foreignKey: 'user_id' }); + +// Many-to-many associations +Task.belongsToMany(Tag, { through: 'tasks_tags', foreignKey: 'task_id', otherKey: 'tag_id' }); +Tag.belongsToMany(Task, { through: 'tasks_tags', foreignKey: 'tag_id', otherKey: 'task_id' }); + +Note.belongsToMany(Tag, { through: 'notes_tags', foreignKey: 'note_id', otherKey: 'tag_id' }); +Tag.belongsToMany(Note, { through: 'notes_tags', foreignKey: 'tag_id', otherKey: 'note_id' }); + +Project.belongsToMany(Tag, { through: 'projects_tags', foreignKey: 'project_id', otherKey: 'tag_id' }); +Tag.belongsToMany(Project, { through: 'projects_tags', foreignKey: 'tag_id', otherKey: 'project_id' }); + +module.exports = { + sequelize, + User, + Area, + Project, + Task, + Tag, + Note, + InboxItem +}; \ No newline at end of file diff --git a/backend/models/note.js b/backend/models/note.js new file mode 100644 index 0000000..a704a4c --- /dev/null +++ b/backend/models/note.js @@ -0,0 +1,47 @@ +const { DataTypes } = require('sequelize'); + +module.exports = (sequelize) => { + const Note = sequelize.define('Note', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true + }, + title: { + type: DataTypes.STRING, + allowNull: true + }, + content: { + type: DataTypes.TEXT, + allowNull: true + }, + user_id: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'users', + key: 'id' + } + }, + project_id: { + type: DataTypes.INTEGER, + allowNull: true, + references: { + model: 'projects', + key: 'id' + } + } + }, { + tableName: 'notes', + indexes: [ + { + fields: ['user_id'] + }, + { + fields: ['project_id'] + } + ] + }); + + return Note; +}; \ No newline at end of file diff --git a/backend/models/project.js b/backend/models/project.js new file mode 100644 index 0000000..af801f3 --- /dev/null +++ b/backend/models/project.js @@ -0,0 +1,69 @@ +const { DataTypes } = require('sequelize'); + +module.exports = (sequelize) => { + const Project = sequelize.define('Project', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true + }, + name: { + type: DataTypes.STRING, + allowNull: false + }, + description: { + type: DataTypes.TEXT, + allowNull: true + }, + active: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }, + pin_to_sidebar: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }, + priority: { + type: DataTypes.INTEGER, + allowNull: true, + validate: { + min: 0, + max: 2 + } + }, + due_date_at: { + type: DataTypes.DATE, + allowNull: true + }, + user_id: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'users', + key: 'id' + } + }, + area_id: { + type: DataTypes.INTEGER, + allowNull: true, + references: { + model: 'areas', + key: 'id' + } + } + }, { + tableName: 'projects', + indexes: [ + { + fields: ['user_id'] + }, + { + fields: ['area_id'] + } + ] + }); + + return Project; +}; \ No newline at end of file diff --git a/backend/models/tag.js b/backend/models/tag.js new file mode 100644 index 0000000..e4894ff --- /dev/null +++ b/backend/models/tag.js @@ -0,0 +1,32 @@ +const { DataTypes } = require('sequelize'); + +module.exports = (sequelize) => { + const Tag = sequelize.define('Tag', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true + }, + name: { + type: DataTypes.STRING, + allowNull: false + }, + user_id: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'users', + key: 'id' + } + } + }, { + tableName: 'tags', + indexes: [ + { + fields: ['user_id'] + } + ] + }); + + return Tag; +}; \ No newline at end of file diff --git a/backend/models/task.js b/backend/models/task.js new file mode 100644 index 0000000..805da80 --- /dev/null +++ b/backend/models/task.js @@ -0,0 +1,127 @@ +const { DataTypes } = require('sequelize'); + +module.exports = (sequelize) => { + const Task = sequelize.define('Task', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true + }, + name: { + type: DataTypes.STRING, + allowNull: false + }, + description: { + type: DataTypes.TEXT, + allowNull: true + }, + due_date: { + type: DataTypes.DATE, + allowNull: true + }, + today: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }, + priority: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: 0, + validate: { + min: 0, + max: 2 + } + }, + status: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + validate: { + min: 0, + max: 4 + } + }, + note: { + type: DataTypes.TEXT, + allowNull: true + }, + recurrence_type: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: 'none' + }, + recurrence_interval: { + type: DataTypes.INTEGER, + allowNull: true + }, + recurrence_end_date: { + type: DataTypes.DATE, + allowNull: true + }, + last_generated_date: { + type: DataTypes.DATE, + allowNull: true + }, + user_id: { + type: DataTypes.INTEGER, + allowNull: false, + references: { + model: 'users', + key: 'id' + } + }, + project_id: { + type: DataTypes.INTEGER, + allowNull: true, + references: { + model: 'projects', + key: 'id' + } + } + }, { + tableName: 'tasks', + indexes: [ + { + fields: ['user_id'] + }, + { + fields: ['project_id'] + }, + { + fields: ['recurrence_type'] + }, + { + fields: ['last_generated_date'] + } + ] + }); + + // Define enum constants + Task.PRIORITY = { + LOW: 0, + MEDIUM: 1, + HIGH: 2 + }; + + Task.STATUS = { + NOT_STARTED: 0, + IN_PROGRESS: 1, + DONE: 2, + ARCHIVED: 3, + WAITING: 4 + }; + + // Instance methods for priority and status + Task.prototype.getPriorityName = function() { + const priorities = ['low', 'medium', 'high']; + return priorities[this.priority] || 'low'; + }; + + Task.prototype.getStatusName = function() { + const statuses = ['not_started', 'in_progress', 'done', 'archived', 'waiting']; + return statuses[this.status] || 'not_started'; + }; + + return Task; +}; \ No newline at end of file diff --git a/backend/models/user.js b/backend/models/user.js new file mode 100644 index 0000000..45c5bd7 --- /dev/null +++ b/backend/models/user.js @@ -0,0 +1,100 @@ +const { DataTypes } = require('sequelize'); +const bcrypt = require('bcrypt'); + +module.exports = (sequelize) => { + const User = sequelize.define('User', { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true + }, + name: { + type: DataTypes.STRING, + allowNull: true + }, + email: { + type: DataTypes.STRING, + allowNull: false, + unique: true, + validate: { + isEmail: true + } + }, + password_digest: { + type: DataTypes.STRING, + allowNull: false, + field: 'password_digest' + }, + appearance: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: 'light', + validate: { + isIn: [['light', 'dark']] + } + }, + language: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: 'en' + }, + timezone: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: 'UTC' + }, + avatar_image: { + type: DataTypes.STRING, + allowNull: true + }, + telegram_bot_token: { + type: DataTypes.STRING, + allowNull: true + }, + telegram_chat_id: { + type: DataTypes.STRING, + allowNull: true + }, + task_summary_enabled: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }, + task_summary_frequency: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: 'daily', + validate: { + isIn: [['daily', 'weekdays', 'weekly', '1h', '2h', '4h', '8h', '12h']] + } + }, + task_summary_last_run: { + type: DataTypes.DATE, + allowNull: true + }, + task_summary_next_run: { + type: DataTypes.DATE, + allowNull: true + } + }, { + tableName: 'users', + hooks: { + beforeValidate: async (user) => { + if (user.password) { + user.password_digest = await bcrypt.hash(user.password, 10); + } + } + } + }); + + // Virtual field for password + User.prototype.setPassword = async function(password) { + this.password_digest = await bcrypt.hash(password, 10); + }; + + User.prototype.checkPassword = async function(password) { + return await bcrypt.compare(password, this.password_digest); + }; + + return User; +}; \ No newline at end of file diff --git a/backend/package-lock.json b/backend/package-lock.json new file mode 100644 index 0000000..fff7bd9 --- /dev/null +++ b/backend/package-lock.json @@ -0,0 +1,8045 @@ +{ + "name": "backend", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "backend", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "bcrypt": "^6.0.0", + "compression": "^1.8.0", + "connect-session-sequelize": "^7.1.7", + "cors": "^2.8.5", + "dotenv": "^16.5.0", + "express": "^4.18.2", + "express-session": "^1.18.1", + "helmet": "^8.1.0", + "js-yaml": "^4.1.0", + "morgan": "^1.10.0", + "multer": "^2.0.1", + "node-cron": "^4.1.0", + "sequelize": "^6.37.7", + "sqlite3": "^5.1.7" + }, + "devDependencies": { + "cross-env": "^7.0.3", + "jest": "^30.0.0", + "nodemon": "^3.0.1", + "sequelize-cli": "^6.6.2", + "supertest": "^7.1.1" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.5.tgz", + "integrity": "sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.4.tgz", + "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.4", + "@babel/parser": "^7.27.4", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.27.4", + "@babel/types": "^7.27.3", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz", + "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.5", + "@babel/types": "^7.27.3", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", + "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz", + "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.4.tgz", + "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/parser": "^7.27.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/types": { + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz", + "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@emnapi/core": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz", + "integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", + "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz", + "integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "license": "MIT", + "optional": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.0.0.tgz", + "integrity": "sha512-vfpJap6JZQ3I8sUN8dsFqNAKJYO4KIGxkcB+3Fw7Q/BJiWY5HwtMMiuT1oP0avsiDhjE/TCLaDgbGfHwDdBVeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.0", + "@types/node": "*", + "chalk": "^4.1.2", + "jest-message-util": "30.0.0", + "jest-util": "30.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/core": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.0.0.tgz", + "integrity": "sha512-1zU39zFtWSl5ZuDK3Rd6P8S28MmS4F11x6Z4CURrgJ99iaAJg68hmdJ2SAHEEO6ociaNk43UhUYtHxWKEWoNYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.0.0", + "@jest/pattern": "30.0.0", + "@jest/reporters": "30.0.0", + "@jest/test-result": "30.0.0", + "@jest/transform": "30.0.0", + "@jest/types": "30.0.0", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-changed-files": "30.0.0", + "jest-config": "30.0.0", + "jest-haste-map": "30.0.0", + "jest-message-util": "30.0.0", + "jest-regex-util": "30.0.0", + "jest-resolve": "30.0.0", + "jest-resolve-dependencies": "30.0.0", + "jest-runner": "30.0.0", + "jest-runtime": "30.0.0", + "jest-snapshot": "30.0.0", + "jest-util": "30.0.0", + "jest-validate": "30.0.0", + "jest-watcher": "30.0.0", + "micromatch": "^4.0.8", + "pretty-format": "30.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/diff-sequences": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.0.tgz", + "integrity": "sha512-xMbtoCeKJDto86GW6AiwVv7M4QAuI56R7dVBr1RNGYbOT44M2TIzOiske2RxopBqkumDY+A1H55pGvuribRY9A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.0.0.tgz", + "integrity": "sha512-09sFbMMgS5JxYnvgmmtwIHhvoyzvR5fUPrVl8nOCrC5KdzmmErTcAxfWyAhJ2bv3rvHNQaKiS+COSG+O7oNbXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "30.0.0", + "@jest/types": "30.0.0", + "@types/node": "*", + "jest-mock": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.0.0.tgz", + "integrity": "sha512-XZ3j6syhMeKiBknmmc8V3mNIb44kxLTbOQtaXA4IFdHy+vEN0cnXRzbRjdGBtrp4k1PWyMWNU3Fjz3iejrhpQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "30.0.0", + "jest-snapshot": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.0.0.tgz", + "integrity": "sha512-UiWfsqNi/+d7xepfOv8KDcbbzcYtkWBe3a3kVDtg6M1kuN6CJ7b4HzIp5e1YHrSaQaVS8sdCoyCMCZClTLNKFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.0.0.tgz", + "integrity": "sha512-yzBmJcrMHAMcAEbV2w1kbxmx8WFpEz8Cth3wjLMSkq+LO8VeGKRhpr5+BUp7PPK+x4njq/b6mVnDR8e/tPL5ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.0", + "@sinonjs/fake-timers": "^13.0.0", + "@types/node": "*", + "jest-message-util": "30.0.0", + "jest-mock": "30.0.0", + "jest-util": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/get-type": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.0.0.tgz", + "integrity": "sha512-VZWMjrBzqfDKngQ7sUctKeLxanAbsBFoZnPxNIG6CmxK7Gv6K44yqd0nzveNIBfuhGZMmk1n5PGbvdSTOu0yTg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.0.0.tgz", + "integrity": "sha512-OEzYes5A1xwBJVMPqFRa8NCao8Vr42nsUZuf/SpaJWoLE+4kyl6nCQZ1zqfipmCrIXQVALC5qJwKy/7NQQLPhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.0.0", + "@jest/expect": "30.0.0", + "@jest/types": "30.0.0", + "jest-mock": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/pattern": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.0.tgz", + "integrity": "sha512-k+TpEThzLVXMkbdxf8KHjZ83Wl+G54ytVJoDIGWwS96Ql4xyASRjc6SU1hs5jHVql+hpyK9G8N7WuFhLpGHRpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.0.0.tgz", + "integrity": "sha512-5WHNlLO0Ok+/o6ML5IzgVm1qyERtLHBNhwn67PAq92H4hZ+n5uW/BYj1VVwmTdxIcNrZLxdV9qtpdZkXf16HxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "30.0.0", + "@jest/test-result": "30.0.0", + "@jest/transform": "30.0.0", + "@jest/types": "30.0.0", + "@jridgewell/trace-mapping": "^0.3.25", + "@types/node": "*", + "chalk": "^4.1.2", + "collect-v8-coverage": "^1.0.2", + "exit-x": "^0.2.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^5.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "30.0.0", + "jest-util": "30.0.0", + "jest-worker": "30.0.0", + "slash": "^3.0.0", + "string-length": "^4.0.2", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/@jest/schemas": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.0.tgz", + "integrity": "sha512-NID2VRyaEkevCRz6badhfqYwri/RvMbiHY81rk3AkK/LaiB0LSxi1RdVZ7MpZdTjNugtZeGfpL0mLs9Kp3MrQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/snapshot-utils": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.0.0.tgz", + "integrity": "sha512-C/QSFUmvZEYptg2Vin84FggAphwHvj6la39vkw1CNOZQORWZ7O/H0BXmdeeeGnvlXDYY8TlFM5jgFnxLAxpFjA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "natural-compare": "^1.4.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.0.tgz", + "integrity": "sha512-oYBJ4d/NF4ZY3/7iq1VaeoERHRvlwKtrGClgescaXMIa1mmb+vfJd0xMgbW9yrI80IUA7qGbxpBWxlITrHkWoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "callsites": "^3.1.0", + "graceful-fs": "^4.2.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.0.0.tgz", + "integrity": "sha512-685zco9HdgBaaWiB9T4xjLtBuN0Q795wgaQPpmuAeZPHwHZSoKFAUnozUtU+ongfi4l5VCz8AclOE5LAQdyjxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.0.0", + "@jest/types": "30.0.0", + "@types/istanbul-lib-coverage": "^2.0.6", + "collect-v8-coverage": "^1.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.0.0.tgz", + "integrity": "sha512-Hmvv5Yg6UmghXIcVZIydkT0nAK7M/hlXx9WMHR5cLVwdmc14/qUQt3mC72T6GN0olPC6DhmKE6Cd/pHsgDbuqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.0.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.0.0.tgz", + "integrity": "sha512-8xhpsCGYJsUjqpJOgLyMkeOSSlhqggFZEWAnZquBsvATtueoEs7CkMRxOUmJliF3E5x+mXmZ7gEEsHank029Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.0.0", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.0", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.0", + "jest-regex-util": "30.0.0", + "jest-util": "30.0.0", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/types": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.0.tgz", + "integrity": "sha512-1Nox8mAL52PKPfEnUQWBvKU/bp8FTT6AiDu76bFDEJj/qsRFSAVSldfCH3XYMqialti2zHXKvD5gN0AaHc0yKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.0", + "@jest/schemas": "30.0.0", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.11.tgz", + "integrity": "sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.9.0" + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "optional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@paralleldrive/cuid2": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz", + "integrity": "sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.1.5" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz", + "integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.35", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.35.tgz", + "integrity": "sha512-C6ypdODf2VZkgRT6sFM8E1F8vR+HcffniX0Kp8MsU8PIfrlXbNCBz0jzj17GjdmjTx1OtZzdH8+iALL21UjF5A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.0.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.1.tgz", + "integrity": "sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.8.0" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/validator": { + "version": "13.15.1", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.1.tgz", + "integrity": "sha512-9gG6ogYcoI2mCMLdcO0NYI0AYrbxIjv0MDmy/5Ywo6CpWWrqYayc+mmgxRsCgtcGJm9BSbXkMsmxGah1iGHAAQ==", + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.9.0.tgz", + "integrity": "sha512-h1T2c2Di49ekF2TE8ZCoJkb+jwETKUIPDJ/nO3tJBKlLFPu+fyd93f0rGP/BvArKx2k2HlRM4kqkNarj3dvZlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.9.0.tgz", + "integrity": "sha512-sG1NHtgXtX8owEkJ11yn34vt0Xqzi3k9TJ8zppDmyG8GZV4kVWw44FHwKwHeEFl07uKPeC4ZoyuQaGh5ruJYPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.9.0.tgz", + "integrity": "sha512-nJ9z47kfFnCxN1z/oYZS7HSNsFh43y2asePzTEZpEvK7kGyuShSl3RRXnm/1QaqFL+iP+BjMwuB+DYUymOkA5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.9.0.tgz", + "integrity": "sha512-TK+UA1TTa0qS53rjWn7cVlEKVGz2B6JYe0C++TdQjvWYIyx83ruwh0wd4LRxYBM5HeuAzXcylA9BH2trARXJTw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.9.0.tgz", + "integrity": "sha512-6uZwzMRFcD7CcCd0vz3Hp+9qIL2jseE/bx3ZjaLwn8t714nYGwiE84WpaMCYjU+IQET8Vu/+BNAGtYD7BG/0yA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.9.0.tgz", + "integrity": "sha512-bPUBksQfrgcfv2+mm+AZinaKq8LCFvt5PThYqRotqSuuZK1TVKkhbVMS/jvSRfYl7jr3AoZLYbDkItxgqMKRkg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.9.0.tgz", + "integrity": "sha512-uT6E7UBIrTdCsFQ+y0tQd3g5oudmrS/hds5pbU3h4s2t/1vsGWbbSKhBSCD9mcqaqkBwoqlECpUrRJCmldl8PA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.9.0.tgz", + "integrity": "sha512-vdqBh911wc5awE2bX2zx3eflbyv8U9xbE/jVKAm425eRoOVv/VseGZsqi3A3SykckSpF4wSROkbQPvbQFn8EsA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.9.0.tgz", + "integrity": "sha512-/8JFZ/SnuDr1lLEVsxsuVwrsGquTvT51RZGvyDB/dOK3oYK2UqeXzgeyq6Otp8FZXQcEYqJwxb9v+gtdXn03eQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.9.0.tgz", + "integrity": "sha512-FkJjybtrl+rajTw4loI3L6YqSOpeZfDls4SstL/5lsP2bka9TiHUjgMBjygeZEis1oC8LfJTS8FSgpKPaQx2tQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.9.0.tgz", + "integrity": "sha512-w/NZfHNeDusbqSZ8r/hp8iL4S39h4+vQMc9/vvzuIKMWKppyUGKm3IST0Qv0aOZ1rzIbl9SrDeIqK86ZpUK37w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.9.0.tgz", + "integrity": "sha512-bEPBosut8/8KQbUixPry8zg/fOzVOWyvwzOfz0C0Rw6dp+wIBseyiHKjkcSyZKv/98edrbMknBaMNJfA/UEdqw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.9.0.tgz", + "integrity": "sha512-LDtMT7moE3gK753gG4pc31AAqGUC86j3AplaFusc717EUGF9ZFJ356sdQzzZzkBk1XzMdxFyZ4f/i35NKM/lFA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.9.0.tgz", + "integrity": "sha512-WmFd5KINHIXj8o1mPaT8QRjA9HgSXhN1gl9Da4IZihARihEnOylu4co7i/yeaIpcfsI6sYs33cNZKyHYDh0lrA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.9.0.tgz", + "integrity": "sha512-CYuXbANW+WgzVRIl8/QvZmDaZxrqvOldOwlbUjIM4pQ46FJ0W5cinJ/Ghwa/Ng1ZPMJMk1VFdsD/XwmCGIXBWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.9.0.tgz", + "integrity": "sha512-6Rp2WH0OoitMYR57Z6VE8Y6corX8C6QEMWLgOV6qXiJIeZ1F9WGXY/yQ8yDC4iTraotyLOeJ2Asea0urWj2fKQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.9.0.tgz", + "integrity": "sha512-rknkrTRuvujprrbPmGeHi8wYWxmNVlBoNW8+4XF2hXUnASOjmuC9FNF1tGbDiRQWn264q9U/oGtixyO3BT8adQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.9.0.tgz", + "integrity": "sha512-Ceymm+iBl+bgAICtgiHyMLz6hjxmLJKqBim8tDzpX61wpZOx2bPK6Gjuor7I2RiUynVjvvkoRIkrPyMwzBzF3A==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.9.0.tgz", + "integrity": "sha512-k59o9ZyeyS0hAlcaKFezYSH2agQeRFEB7KoQLXl3Nb3rgkqT1NY9Vwy+SqODiLmYnEjxWJVRE/yq2jFVqdIxZw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC", + "optional": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "optional": true + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "license": "MIT" + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "license": "ISC", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/babel-jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.0.0.tgz", + "integrity": "sha512-JQ0DhdFjODbSawDf0026uZuwaqfKkQzk+9mwWkq2XkKFIaMhFVOxlVmbFCOnnC76jATdxrff3IiUAvOAJec6tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "30.0.0", + "@types/babel__core": "^7.20.5", + "babel-plugin-istanbul": "^7.0.0", + "babel-preset-jest": "30.0.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz", + "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.0.0.tgz", + "integrity": "sha512-DSRm+US/FCB4xPDD6Rnslb6PAF9Bej1DZ+1u4aTiqJnk7ZX12eHsnDiIOqjGvITCq+u6wLqUhgS+faCNbVY8+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3", + "@types/babel__core": "^7.20.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.0.0.tgz", + "integrity": "sha512-hgEuu/W7gk8QOWUA9+m3Zk+WpGvKc1Egp6rFQEfYxEoM9Fk/q8nuTXNL65OkhwGrTApauEGgakOoWVXj+UfhKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "30.0.0", + "babel-preset-current-node-syntax": "^1.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", + "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001718", + "electron-to-chromium": "^1.5.160", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "optional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001723", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz", + "integrity": "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.2.0.tgz", + "integrity": "sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.0.tgz", + "integrity": "sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==", + "dev": true, + "license": "MIT" + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.0.tgz", + "integrity": "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.0.2", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/connect-session-sequelize": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/connect-session-sequelize/-/connect-session-sequelize-7.1.7.tgz", + "integrity": "sha512-Wqq7rg0w+9bOVs6jC0nhZnssXJ3+iKNlDVWn2JfBuBPoY7oYaxzxfBKeUYrX6dHt3OWEWbZV6LJvapwi76iBQQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.1" + }, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "sequelize": ">= 6.1.0" + } + }, + "node_modules/connect-session-sequelize/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/connect-session-sequelize/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC", + "optional": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dedent": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", + "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT", + "optional": true + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "license": "ISC", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/dotenv": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dottie": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", + "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==", + "license": "MIT" + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/editorconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" + }, + "bin": { + "editorconfig": "bin/editorconfig" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/editorconfig/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/editorconfig/node_modules/minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.167", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.167.tgz", + "integrity": "sha512-LxcRvnYO5ez2bMOFpbuuVuAI5QNeY1ncVytE/KXaL6ZNfzX1yPlAO0nSOyIHx2fVAuUprMqPs/TdVhUFZy7SIQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT", + "optional": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit-x": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", + "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/expect": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.0.tgz", + "integrity": "sha512-xCdPp6gwiR9q9lsPCHANarIkFTN/IMZso6Kkq03sOm9IIGtzK/UJqml0dkhHibGh8HKOj8BIDIpZ0BZuU7QK6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "30.0.0", + "@jest/get-type": "30.0.0", + "jest-matcher-utils": "30.0.0", + "jest-message-util": "30.0.0", + "jest-mock": "30.0.0", + "jest-util": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-session": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.1.tgz", + "integrity": "sha512-a5mtTqEaZvBCL9A9aqkrtfz+3SMDhOVUnjafjo+s7A9Txkq+SVX2DLvSp1Zrv4uCXa3lMSK3viWnh9Gg07PBUA==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.7", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/express/node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", + "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formidable": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", + "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@paralleldrive/cuid2": "^2.2.2", + "dezalgo": "^1.0.4", + "once": "^1.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "devOptional": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC", + "optional": true + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/helmet": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.1.0.tgz", + "integrity": "sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "optional": true + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "optional": true + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true, + "license": "ISC" + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "license": "ISC", + "optional": true + }, + "node_modules/inflection": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", + "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", + "engines": [ + "node >= 0.4.0" + ], + "license": "MIT" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "devOptional": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "license": "MIT", + "optional": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "license": "MIT", + "optional": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.0.0.tgz", + "integrity": "sha512-/3G2iFwsUY95vkflmlDn/IdLyLWqpQXcftptooaPH4qkyU52V7qVYf1BjmdSPlp1+0fs6BmNtrGaSFwOfV07ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "30.0.0", + "@jest/types": "30.0.0", + "import-local": "^3.2.0", + "jest-cli": "30.0.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.0.0.tgz", + "integrity": "sha512-rzGpvCdPdEV1Ma83c1GbZif0L2KAm3vXSXGRlpx7yCt0vhruwCNouKNRh3SiVcISHP1mb3iJzjb7tAEnNu1laQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.1.1", + "jest-util": "30.0.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-circus": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.0.0.tgz", + "integrity": "sha512-nTwah78qcKVyndBS650hAkaEmwWGaVsMMoWdJwMnH77XArRJow2Ir7hc+8p/mATtxVZuM9OTkA/3hQocRIK5Dw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.0.0", + "@jest/expect": "30.0.0", + "@jest/test-result": "30.0.0", + "@jest/types": "30.0.0", + "@types/node": "*", + "chalk": "^4.1.2", + "co": "^4.6.0", + "dedent": "^1.6.0", + "is-generator-fn": "^2.1.0", + "jest-each": "30.0.0", + "jest-matcher-utils": "30.0.0", + "jest-message-util": "30.0.0", + "jest-runtime": "30.0.0", + "jest-snapshot": "30.0.0", + "jest-util": "30.0.0", + "p-limit": "^3.1.0", + "pretty-format": "30.0.0", + "pure-rand": "^7.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-cli": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.0.0.tgz", + "integrity": "sha512-fWKAgrhlwVVCfeizsmIrPRTBYTzO82WSba3gJniZNR3PKXADgdC0mmCSK+M+t7N8RCXOVfY6kvCkvjUNtzmHYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "30.0.0", + "@jest/test-result": "30.0.0", + "@jest/types": "30.0.0", + "chalk": "^4.1.2", + "exit-x": "^0.2.2", + "import-local": "^3.2.0", + "jest-config": "30.0.0", + "jest-util": "30.0.0", + "jest-validate": "30.0.0", + "yargs": "^17.7.2" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-cli/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-cli/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-config": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.0.0.tgz", + "integrity": "sha512-p13a/zun+sbOMrBnTEUdq/5N7bZMOGd1yMfqtAJniPNuzURMay4I+vxZLK1XSDbjvIhmeVdG8h8RznqYyjctyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/get-type": "30.0.0", + "@jest/pattern": "30.0.0", + "@jest/test-sequencer": "30.0.0", + "@jest/types": "30.0.0", + "babel-jest": "30.0.0", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "deepmerge": "^4.3.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-circus": "30.0.0", + "jest-docblock": "30.0.0", + "jest-environment-node": "30.0.0", + "jest-regex-util": "30.0.0", + "jest-resolve": "30.0.0", + "jest-runner": "30.0.0", + "jest-util": "30.0.0", + "jest-validate": "30.0.0", + "micromatch": "^4.0.8", + "parse-json": "^5.2.0", + "pretty-format": "30.0.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "esbuild-register": ">=3.4.0", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "esbuild-register": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/jest-config/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/jest-config/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-diff": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.0.tgz", + "integrity": "sha512-TgT1+KipV8JTLXXeFX0qSvIJR/UXiNNojjxb/awh3vYlBZyChU/NEmyKmq+wijKjWEztyrGJFL790nqMqNjTHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.0", + "@jest/get-type": "30.0.0", + "chalk": "^4.1.2", + "pretty-format": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.0.0.tgz", + "integrity": "sha512-By/iQ0nvTzghEecGzUMCp1axLtBh+8wB4Hpoi5o+x1stycjEmPcH1mHugL4D9Q+YKV++vKeX/3ZTW90QC8ICPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-each": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.0.0.tgz", + "integrity": "sha512-qkFEW3cfytEjG2KtrhwtldZfXYnWSanO8xUMXLe4A6yaiHMHJUalk0Yyv4MQH6aeaxgi4sGVrukvF0lPMM7U1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.0", + "@jest/types": "30.0.0", + "chalk": "^4.1.2", + "jest-util": "30.0.0", + "pretty-format": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.0.0.tgz", + "integrity": "sha512-sF6lxyA25dIURyDk4voYmGU9Uwz2rQKMfjxKnDd19yk+qxKGrimFqS5YsPHWTlAVBo+YhWzXsqZoaMzrTFvqfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.0.0", + "@jest/fake-timers": "30.0.0", + "@jest/types": "30.0.0", + "@types/node": "*", + "jest-mock": "30.0.0", + "jest-util": "30.0.0", + "jest-validate": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.0.tgz", + "integrity": "sha512-p4bXAhXTawTsADgQgTpbymdLaTyPW1xWNu1oIGG7/N3LIAbZVkH2JMJqS8/IUcnGR8Kc7WFE+vWbJvsqGCWZXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.0", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.0", + "jest-util": "30.0.0", + "jest-worker": "30.0.0", + "micromatch": "^4.0.8", + "walker": "^1.0.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.3" + } + }, + "node_modules/jest-leak-detector": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.0.0.tgz", + "integrity": "sha512-E/ly1azdVVbZrS0T6FIpyYHvsdek4FNaThJTtggjV/8IpKxh3p9NLndeUZy2+sjAI3ncS+aM0uLLon/dBg8htA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.0", + "pretty-format": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.0.0.tgz", + "integrity": "sha512-m5mrunqopkrqwG1mMdJxe1J4uGmS9AHHKYUmoxeQOxBcLjEvirIrIDwuKmUYrecPHVB/PUBpXs2gPoeA2FSSLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.0", + "chalk": "^4.1.2", + "jest-diff": "30.0.0", + "pretty-format": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.0.tgz", + "integrity": "sha512-pV3qcrb4utEsa/U7UI2VayNzSDQcmCllBZLSoIucrESRu0geKThFZOjjh0kACDJFJRAQwsK7GVsmS6SpEceD8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.0.0", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-mock": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.0.tgz", + "integrity": "sha512-W2sRA4ALXILrEetEOh2ooZG6fZ01iwVs0OWMKSSWRcUlaLr4ESHuiKXDNTg+ZVgOq8Ei5445i/Yxrv59VT+XkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.0", + "@types/node": "*", + "jest-util": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.0.tgz", + "integrity": "sha512-rT84010qRu/5OOU7a9TeidC2Tp3Qgt9Sty4pOZ/VSDuEmRupIjKZAb53gU3jr4ooMlhwScrgC9UixJxWzVu9oQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.0.0.tgz", + "integrity": "sha512-zwWl1P15CcAfuQCEuxszjiKdsValhnWcj/aXg/R3aMHs8HVoCWHC4B/+5+1BirMoOud8NnN85GSP2LEZCbj3OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.0", + "jest-pnp-resolver": "^1.2.3", + "jest-util": "30.0.0", + "jest-validate": "30.0.0", + "slash": "^3.0.0", + "unrs-resolver": "^1.7.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.0.0.tgz", + "integrity": "sha512-Yhh7odCAUNXhluK1bCpwIlHrN1wycYaTlZwq1GdfNBEESNNI/z1j1a7dUEWHbmB9LGgv0sanxw3JPmWU8NeebQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "30.0.0", + "jest-snapshot": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runner": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.0.0.tgz", + "integrity": "sha512-xbhmvWIc8X1IQ8G7xTv0AQJXKjBVyxoVJEJgy7A4RXsSaO+k/1ZSBbHwjnUhvYqMvwQPomWssDkUx6EoidEhlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.0.0", + "@jest/environment": "30.0.0", + "@jest/test-result": "30.0.0", + "@jest/transform": "30.0.0", + "@jest/types": "30.0.0", + "@types/node": "*", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-docblock": "30.0.0", + "jest-environment-node": "30.0.0", + "jest-haste-map": "30.0.0", + "jest-leak-detector": "30.0.0", + "jest-message-util": "30.0.0", + "jest-resolve": "30.0.0", + "jest-runtime": "30.0.0", + "jest-util": "30.0.0", + "jest-watcher": "30.0.0", + "jest-worker": "30.0.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.0.0.tgz", + "integrity": "sha512-/O07qVgFrFAOGKGigojmdR3jUGz/y3+a/v9S/Yi2MHxsD+v6WcPppglZJw0gNJkRBArRDK8CFAwpM/VuEiiRjA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.0.0", + "@jest/fake-timers": "30.0.0", + "@jest/globals": "30.0.0", + "@jest/source-map": "30.0.0", + "@jest/test-result": "30.0.0", + "@jest/transform": "30.0.0", + "@jest/types": "30.0.0", + "@types/node": "*", + "chalk": "^4.1.2", + "cjs-module-lexer": "^2.1.0", + "collect-v8-coverage": "^1.0.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.0", + "jest-message-util": "30.0.0", + "jest-mock": "30.0.0", + "jest-regex-util": "30.0.0", + "jest-resolve": "30.0.0", + "jest-snapshot": "30.0.0", + "jest-util": "30.0.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/jest-snapshot": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.0.0.tgz", + "integrity": "sha512-6oCnzjpvfj/UIOMTqKZ6gedWAUgaycMdV8Y8h2dRJPvc2wSjckN03pzeoonw8y33uVngfx7WMo1ygdRGEKOT7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.0.0", + "@jest/get-type": "30.0.0", + "@jest/snapshot-utils": "30.0.0", + "@jest/transform": "30.0.0", + "@jest/types": "30.0.0", + "babel-preset-current-node-syntax": "^1.1.0", + "chalk": "^4.1.2", + "expect": "30.0.0", + "graceful-fs": "^4.2.11", + "jest-diff": "30.0.0", + "jest-matcher-utils": "30.0.0", + "jest-message-util": "30.0.0", + "jest-util": "30.0.0", + "pretty-format": "30.0.0", + "semver": "^7.7.2", + "synckit": "^0.11.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-util": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.0.tgz", + "integrity": "sha512-fhNBBM9uSUbd4Lzsf8l/kcAdaHD/4SgoI48en3HXcBEMwKwoleKFMZ6cYEYs21SB779PRuRCyNLmymApAm8tZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.0", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-util/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-validate": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.0.0.tgz", + "integrity": "sha512-d6OkzsdlWItHAikUDs1hlLmpOIRhsZoXTCliV2XXalVQ3ZOeb9dy0CQ6AKulJu/XOZqpOEr/FiMH+FeOBVV+nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.0", + "@jest/types": "30.0.0", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "leven": "^3.1.0", + "pretty-format": "30.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.0.0.tgz", + "integrity": "sha512-fbAkojcyS53bOL/B7XYhahORq9cIaPwOgd/p9qW/hybbC8l6CzxfWJJxjlPBAIVN8dRipLR0zdhpGQdam+YBtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.0.0", + "@jest/types": "30.0.0", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "jest-util": "30.0.0", + "string-length": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-worker": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.0.tgz", + "integrity": "sha512-VZvxfWIybIvwK8N/Bsfe43LfQgd/rD0c4h5nLUx78CAqPxIQcW2qDjsVAC53iUR8yxzFIeCFFvWOh8en8hGzdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.0.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-beautify": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz", + "integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "config-chain": "^1.1.13", + "editorconfig": "^1.0.4", + "glob": "^10.4.2", + "js-cookie": "^3.0.5", + "nopt": "^7.2.1" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/js-beautify/node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/js-beautify/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/js-beautify/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/js-beautify/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/js-beautify/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/js-beautify/node_modules/nopt": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", + "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "license": "MIT", + "optional": true + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "license": "ISC", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.48", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz", + "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==", + "license": "MIT", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "license": "MIT", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/multer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.1.tgz", + "integrity": "sha512-Ug8bXeTIUlxurg8xLTEskKShvcKDZALo1THEX5E41pYCD2sCVub5/kIRIGqWNoqV6szyLyQKV6mD4QUrWE5GCQ==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", + "object-assign": "^4.1.1", + "type-is": "^1.6.18", + "xtend": "^4.0.2" + }, + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, + "node_modules/napi-postinstall": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.4.tgz", + "integrity": "sha512-ZEzHJwBhZ8qQSbknHqYcdtQVr8zUgGyM/q6h6qAyhtyVMNrSgDhrC4disf03dYW0e+czXyLnZINnCTEkWy0eJg==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-abi": { + "version": "3.75.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz", + "integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.4.0.tgz", + "integrity": "sha512-D9DI/gXHvVmjHS08SVch0Em8G5S1P+QWtU31appcKT/8wFSPRcdHadIFSAntdMMVM5zz+/DL+bL/gz3UDppqtg==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/node-cron": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-4.1.0.tgz", + "integrity": "sha512-OS+3ORu+h03/haS6Di8Qr7CrVs4YaKZZOynZwQpyPZDnR3tqRbwJmuP2gVR16JfhLgyNlloAV1VTrrWlRogCFA==", + "license": "ISC", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "license": "MIT", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/nodemon": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.10.tgz", + "integrity": "sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "node_modules/pg-connection-string": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.0.tgz", + "integrity": "sha512-P2DEBKuvh5RClafLngkAuGe9OUlFV7ebu8w1kmaaOgPcpJd1RIFh7otETfI6hAR8YupOLFTY7nuvvIn7PLciUQ==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pretty-format": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.0.tgz", + "integrity": "sha512-18NAOUr4ZOQiIR+BgI5NhQE7uREdx4ZyV0dyay5izh4yfQ+1T7BSvggxvRGoXocrRyevqW5OhScUjbi9GB8R8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.0", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "license": "ISC", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true, + "license": "ISC" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pure-rand": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", + "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/retry-as-promised": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.1.1.tgz", + "integrity": "sha512-hMD7odLOt3LkTjcif8aRZqi/hybjpLNgSk5oF5FCowfCjok6LukpN2bDX7R5wDmbgBQFn7YoBxSagmtXHaJYJw==", + "license": "MIT" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/sequelize": { + "version": "6.37.7", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.37.7.tgz", + "integrity": "sha512-mCnh83zuz7kQxxJirtFD7q6Huy6liPanI67BSlbzSYgVNl5eXVdE2CN1FuAeZwG1SNpGsNRCV+bJAVVnykZAFA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/sequelize" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.1.8", + "@types/validator": "^13.7.17", + "debug": "^4.3.4", + "dottie": "^2.0.6", + "inflection": "^1.13.4", + "lodash": "^4.17.21", + "moment": "^2.29.4", + "moment-timezone": "^0.5.43", + "pg-connection-string": "^2.6.1", + "retry-as-promised": "^7.0.4", + "semver": "^7.5.4", + "sequelize-pool": "^7.1.0", + "toposort-class": "^1.0.1", + "uuid": "^8.3.2", + "validator": "^13.9.0", + "wkx": "^0.5.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependenciesMeta": { + "ibm_db": { + "optional": true + }, + "mariadb": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-hstore": { + "optional": true + }, + "snowflake-sdk": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/sequelize-cli": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.6.3.tgz", + "integrity": "sha512-1YYPrcSRt/bpMDDSKM5ubY1mnJ2TEwIaGZcqITw4hLtGtE64nIqaBnLtMvH8VKHg6FbWpXTiFNc2mS/BtQCXZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fs-extra": "^9.1.0", + "js-beautify": "1.15.4", + "lodash": "^4.17.21", + "picocolors": "^1.1.1", + "resolve": "^1.22.1", + "umzug": "^2.3.0", + "yargs": "^16.2.0" + }, + "bin": { + "sequelize": "lib/sequelize", + "sequelize-cli": "lib/sequelize" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/sequelize-pool": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", + "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/sequelize/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/sequelize/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC", + "optional": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz", + "integrity": "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==", + "license": "MIT", + "optional": true, + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/socks-proxy-agent/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socks-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "optional": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/sqlite3": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", + "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/sqlite3/node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/superagent": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.2.1.tgz", + "integrity": "sha512-O+PCv11lgTNJUzy49teNAWLjBZfc+A1enOwTpLlH6/rsvKcTwcdTT8m9azGkVqM7HBl5jpyZ7KTPhHweokBcdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^3.5.4", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/superagent/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/superagent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/supertest": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.1.tgz", + "integrity": "sha512-aI59HBTlG9e2wTjxGJV+DygfNLgnWbGdZxiA/sgrnNNikIW8lbDvCtF6RnhZoJ82nU7qv7ZLjrvWqCEm52fAmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "methods": "^1.1.2", + "superagent": "^10.2.1" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/synckit": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz", + "integrity": "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.4" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-fs": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", + "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==", + "license": "MIT" + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "license": "ISC", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "license": "MIT" + }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "license": "MIT", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/umzug": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", + "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bluebird": "^3.7.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", + "license": "MIT" + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "license": "ISC", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unrs-resolver": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.9.0.tgz", + "integrity": "sha512-wqaRu4UnzBD2ABTC1kLfBjAqIDZ5YUTr/MLGa7By47JV1bJDSW7jq/ZSLigB7enLe7ubNaJhtnBXgrc/50cEhg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.2.2" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.9.0", + "@unrs/resolver-binding-android-arm64": "1.9.0", + "@unrs/resolver-binding-darwin-arm64": "1.9.0", + "@unrs/resolver-binding-darwin-x64": "1.9.0", + "@unrs/resolver-binding-freebsd-x64": "1.9.0", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.9.0", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.9.0", + "@unrs/resolver-binding-linux-arm64-gnu": "1.9.0", + "@unrs/resolver-binding-linux-arm64-musl": "1.9.0", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.9.0", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.9.0", + "@unrs/resolver-binding-linux-riscv64-musl": "1.9.0", + "@unrs/resolver-binding-linux-s390x-gnu": "1.9.0", + "@unrs/resolver-binding-linux-x64-gnu": "1.9.0", + "@unrs/resolver-binding-linux-x64-musl": "1.9.0", + "@unrs/resolver-binding-wasm32-wasi": "1.9.0", + "@unrs/resolver-binding-win32-arm64-msvc": "1.9.0", + "@unrs/resolver-binding-win32-ia32-msvc": "1.9.0", + "@unrs/resolver-binding-win32-x64-msvc": "1.9.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/validator": { + "version": "13.15.15", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.15.tgz", + "integrity": "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wkx": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", + "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/backend/package.json b/backend/package.json new file mode 100644 index 0000000..84a2dd3 --- /dev/null +++ b/backend/package.json @@ -0,0 +1,52 @@ +{ + "name": "backend", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "start": "node app.js", + "dev": "nodemon app.js", + "test": "cross-env NODE_ENV=test jest", + "test:watch": "cross-env NODE_ENV=test jest --watch", + "test:coverage": "cross-env NODE_ENV=test jest --coverage", + "test:unit": "cross-env NODE_ENV=test jest tests/unit", + "test:integration": "cross-env NODE_ENV=test jest tests/integration", + "db:init": "node scripts/db-init.js", + "db:sync": "node scripts/db-sync.js", + "db:migrate": "node scripts/db-migrate.js", + "db:reset": "node scripts/db-reset.js", + "db:status": "node scripts/db-status.js", + "user:create": "node scripts/user-create.js", + "migration:create": "node scripts/migration-create.js", + "migration:run": "npx sequelize-cli db:migrate", + "migration:undo": "npx sequelize-cli db:migrate:undo", + "migration:undo:all": "npx sequelize-cli db:migrate:undo:all", + "migration:status": "npx sequelize-cli db:migrate:status" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "bcrypt": "^6.0.0", + "compression": "^1.8.0", + "connect-session-sequelize": "^7.1.7", + "cors": "^2.8.5", + "dotenv": "^16.5.0", + "express": "^4.18.2", + "express-session": "^1.18.1", + "helmet": "^8.1.0", + "js-yaml": "^4.1.0", + "morgan": "^1.10.0", + "multer": "^2.0.1", + "node-cron": "^4.1.0", + "sequelize": "^6.37.7", + "sqlite3": "^5.1.7" + }, + "devDependencies": { + "cross-env": "^7.0.3", + "jest": "^30.0.0", + "nodemon": "^3.0.1", + "sequelize-cli": "^6.6.2", + "supertest": "^7.1.1" + } +} diff --git a/backend/routes/areas.js b/backend/routes/areas.js new file mode 100644 index 0000000..84607b8 --- /dev/null +++ b/backend/routes/areas.js @@ -0,0 +1,130 @@ +const express = require('express'); +const { Area } = require('../models'); +const router = express.Router(); + +// GET /api/areas +router.get('/areas', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const areas = await Area.findAll({ + where: { user_id: req.session.userId }, + order: [['name', 'ASC']] + }); + + res.json(areas); + } catch (error) { + console.error('Error fetching areas:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// GET /api/areas/:id +router.get('/areas/:id', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const area = await Area.findOne({ + where: { id: req.params.id, user_id: req.session.userId } + }); + + if (!area) { + return res.status(404).json({ error: "Area not found or doesn't belong to the current user." }); + } + + res.json(area); + } catch (error) { + console.error('Error fetching area:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// POST /api/areas +router.post('/areas', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const { name, description } = req.body; + + if (!name || !name.trim()) { + return res.status(400).json({ error: 'Area name is required.' }); + } + + const area = await Area.create({ + name: name.trim(), + description: description || '', + user_id: req.session.userId + }); + + res.status(201).json(area); + } catch (error) { + console.error('Error creating area:', error); + res.status(400).json({ + error: 'There was a problem creating the area.', + details: error.errors ? error.errors.map(e => e.message) : [error.message] + }); + } +}); + +// PATCH /api/areas/:id +router.patch('/areas/:id', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const area = await Area.findOne({ + where: { id: req.params.id, user_id: req.session.userId } + }); + + if (!area) { + return res.status(404).json({ error: 'Area not found.' }); + } + + const { name, description } = req.body; + const updateData = {}; + + if (name !== undefined) updateData.name = name; + if (description !== undefined) updateData.description = description; + + await area.update(updateData); + res.json(area); + } catch (error) { + console.error('Error updating area:', error); + res.status(400).json({ + error: 'There was a problem updating the area.', + details: error.errors ? error.errors.map(e => e.message) : [error.message] + }); + } +}); + +// DELETE /api/areas/:id +router.delete('/areas/:id', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const area = await Area.findOne({ + where: { id: req.params.id, user_id: req.session.userId } + }); + + if (!area) { + return res.status(404).json({ error: 'Area not found.' }); + } + + await area.destroy(); + res.status(204).send(); + } catch (error) { + console.error('Error deleting area:', error); + res.status(400).json({ error: 'There was a problem deleting the area.' }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/auth.js b/backend/routes/auth.js new file mode 100644 index 0000000..e6ea09e --- /dev/null +++ b/backend/routes/auth.js @@ -0,0 +1,78 @@ +const express = require('express'); +const { User } = require('../models'); +const router = express.Router(); + +// Get current user +router.get('/current_user', async (req, res) => { + try { + if (req.session && req.session.userId) { + const user = await User.findByPk(req.session.userId); + if (user) { + return res.json({ + user: { + id: user.id, + email: user.email, + language: user.language, + appearance: user.appearance, + timezone: user.timezone + } + }); + } + } + + res.json({ user: null }); + } catch (error) { + console.error('Error fetching current user:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// Login +router.post('/login', async (req, res) => { + try { + const { email, password } = req.body; + + if (!email || !password) { + return res.status(400).json({ error: 'Invalid login parameters.' }); + } + + const user = await User.findOne({ where: { email } }); + if (!user) { + return res.status(401).json({ errors: ['Invalid credentials'] }); + } + + const isValidPassword = await user.checkPassword(password); + if (!isValidPassword) { + return res.status(401).json({ errors: ['Invalid credentials'] }); + } + + req.session.userId = user.id; + + res.json({ + user: { + id: user.id, + email: user.email, + language: user.language, + appearance: user.appearance, + timezone: user.timezone + } + }); + } catch (error) { + console.error('Login error:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// Logout +router.get('/logout', (req, res) => { + req.session.destroy((err) => { + if (err) { + console.error('Logout error:', err); + return res.status(500).json({ error: 'Could not log out' }); + } + + res.json({ message: 'Logged out successfully' }); + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/inbox.js b/backend/routes/inbox.js new file mode 100644 index 0000000..a7bde05 --- /dev/null +++ b/backend/routes/inbox.js @@ -0,0 +1,157 @@ +const express = require('express'); +const { InboxItem } = require('../models'); +const router = express.Router(); + +// GET /api/inbox +router.get('/inbox', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const items = await InboxItem.findAll({ + where: { + user_id: req.session.userId, + status: 'added' + }, + order: [['created_at', 'DESC']] + }); + + res.json(items); + } catch (error) { + console.error('Error fetching inbox items:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// POST /api/inbox +router.post('/inbox', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const { content, source } = req.body; + + if (!content || !content.trim()) { + return res.status(400).json({ error: 'Content is required' }); + } + + const item = await InboxItem.create({ + content: content.trim(), + source: source || 'tududi', + user_id: req.session.userId + }); + + res.status(201).json(item); + } catch (error) { + console.error('Error creating inbox item:', error); + res.status(400).json({ + error: 'There was a problem creating the inbox item.', + details: error.errors ? error.errors.map(e => e.message) : [error.message] + }); + } +}); + +// GET /api/inbox/:id +router.get('/inbox/:id', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const item = await InboxItem.findOne({ + where: { id: req.params.id, user_id: req.session.userId } + }); + + if (!item) { + return res.status(404).json({ error: 'Inbox item not found.' }); + } + + res.json(item); + } catch (error) { + console.error('Error fetching inbox item:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// PATCH /api/inbox/:id +router.patch('/inbox/:id', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const item = await InboxItem.findOne({ + where: { id: req.params.id, user_id: req.session.userId } + }); + + if (!item) { + return res.status(404).json({ error: 'Inbox item not found.' }); + } + + const { content, status } = req.body; + const updateData = {}; + + if (content !== undefined) updateData.content = content; + if (status !== undefined) updateData.status = status; + + await item.update(updateData); + res.json(item); + } catch (error) { + console.error('Error updating inbox item:', error); + res.status(400).json({ + error: 'There was a problem updating the inbox item.', + details: error.errors ? error.errors.map(e => e.message) : [error.message] + }); + } +}); + +// DELETE /api/inbox/:id +router.delete('/inbox/:id', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const item = await InboxItem.findOne({ + where: { id: req.params.id, user_id: req.session.userId } + }); + + if (!item) { + return res.status(404).json({ error: 'Inbox item not found.' }); + } + + // Mark as deleted instead of actual deletion + await item.update({ status: 'deleted' }); + res.json({ message: 'Inbox item successfully deleted' }); + } catch (error) { + console.error('Error deleting inbox item:', error); + res.status(400).json({ error: 'There was a problem deleting the inbox item.' }); + } +}); + +// PATCH /api/inbox/:id/process +router.patch('/inbox/:id/process', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const item = await InboxItem.findOne({ + where: { id: req.params.id, user_id: req.session.userId } + }); + + if (!item) { + return res.status(404).json({ error: 'Inbox item not found.' }); + } + + await item.update({ status: 'processed' }); + res.json(item); + } catch (error) { + console.error('Error processing inbox item:', error); + res.status(400).json({ error: 'There was a problem processing the inbox item.' }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/notes.js b/backend/routes/notes.js new file mode 100644 index 0000000..ea080d6 --- /dev/null +++ b/backend/routes/notes.js @@ -0,0 +1,242 @@ +const express = require('express'); +const { Note, Tag, Project, sequelize } = require('../models'); +const { Op } = require('sequelize'); +const router = express.Router(); + +// Helper function to update note tags +async function updateNoteTags(note, tagsArray, userId) { + if (!tagsArray || tagsArray.length === 0) { + await note.setTags([]); + return; + } + + try { + const tagNames = tagsArray.filter((name, index, arr) => arr.indexOf(name) === index); // unique + const tags = await Promise.all( + tagNames.map(async (name) => { + const [tag] = await Tag.findOrCreate({ + where: { name, user_id: userId }, + defaults: { name, user_id: userId } + }); + return tag; + }) + ); + await note.setTags(tags); + } catch (error) { + console.error('Failed to update tags:', error.message); + } +} + +// GET /api/notes +router.get('/notes', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const orderBy = req.query.order_by || 'title:asc'; + const [orderColumn, orderDirection] = orderBy.split(':'); + + let whereClause = { user_id: req.session.userId }; + let includeClause = [ + { model: Tag, through: { attributes: [] } }, + { model: Project, required: false, attributes: ['id', 'name'] } + ]; + + // Filter by tag + if (req.query.tag) { + includeClause[0].where = { name: req.query.tag }; + includeClause[0].required = true; + } + + const notes = await Note.findAll({ + where: whereClause, + include: includeClause, + order: [[orderColumn, orderDirection.toUpperCase()]], + distinct: true + }); + + res.json(notes); + } catch (error) { + console.error('Error fetching notes:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// GET /api/note/:id +router.get('/note/:id', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const note = await Note.findOne({ + where: { id: req.params.id, user_id: req.session.userId }, + include: [ + { model: Tag, through: { attributes: [] } }, + { model: Project, required: false, attributes: ['id', 'name'] } + ] + }); + + if (!note) { + return res.status(404).json({ error: 'Note not found.' }); + } + + res.json(note); + } catch (error) { + console.error('Error fetching note:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// POST /api/note +router.post('/note', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const { title, content, project_id, tags } = req.body; + + const noteAttributes = { + title, + content, + user_id: req.session.userId + }; + + // Handle project assignment + if (project_id && project_id.toString().trim()) { + const project = await Project.findOne({ + where: { id: project_id, user_id: req.session.userId } + }); + if (!project) { + return res.status(400).json({ error: 'Invalid project.' }); + } + noteAttributes.project_id = project_id; + } + + const note = await Note.create(noteAttributes); + + // Handle tags - can be array of strings or array of objects with name property + let tagNames = []; + if (Array.isArray(tags)) { + if (tags.every(t => typeof t === 'string')) { + tagNames = tags; + } else if (tags.every(t => typeof t === 'object' && t.name)) { + tagNames = tags.map(t => t.name); + } + } + + await updateNoteTags(note, tagNames, req.session.userId); + + // Reload note with associations + const noteWithAssociations = await Note.findByPk(note.id, { + include: [ + { model: Tag, through: { attributes: [] } }, + { model: Project, required: false, attributes: ['id', 'name'] } + ] + }); + + res.status(201).json(noteWithAssociations); + } catch (error) { + console.error('Error creating note:', error); + res.status(400).json({ + error: 'There was a problem creating the note.', + details: error.errors ? error.errors.map(e => e.message) : [error.message] + }); + } +}); + +// PATCH /api/note/:id +router.patch('/note/:id', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const note = await Note.findOne({ + where: { id: req.params.id, user_id: req.session.userId } + }); + + if (!note) { + return res.status(404).json({ error: 'Note not found.' }); + } + + const { title, content, project_id, tags } = req.body; + + const updateData = {}; + if (title !== undefined) updateData.title = title; + if (content !== undefined) updateData.content = content; + + // Handle project assignment + if (project_id !== undefined) { + if (project_id && project_id.toString().trim()) { + const project = await Project.findOne({ + where: { id: project_id, user_id: req.session.userId } + }); + if (!project) { + return res.status(400).json({ error: 'Invalid project.' }); + } + updateData.project_id = project_id; + } else { + updateData.project_id = null; + } + } + + await note.update(updateData); + + // Handle tags if provided + if (tags !== undefined) { + let tagNames = []; + if (Array.isArray(tags)) { + if (tags.every(t => typeof t === 'string')) { + tagNames = tags; + } else if (tags.every(t => typeof t === 'object' && t.name)) { + tagNames = tags.map(t => t.name); + } + } + await updateNoteTags(note, tagNames, req.session.userId); + } + + // Reload note with associations + const noteWithAssociations = await Note.findByPk(note.id, { + include: [ + { model: Tag, through: { attributes: [] } }, + { model: Project, required: false, attributes: ['id', 'name'] } + ] + }); + + res.json(noteWithAssociations); + } catch (error) { + console.error('Error updating note:', error); + res.status(400).json({ + error: 'There was a problem updating the note.', + details: error.errors ? error.errors.map(e => e.message) : [error.message] + }); + } +}); + +// DELETE /api/note/:id +router.delete('/note/:id', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const note = await Note.findOne({ + where: { id: req.params.id, user_id: req.session.userId } + }); + + if (!note) { + return res.status(404).json({ error: 'Note not found.' }); + } + + await note.destroy(); + res.json({ message: 'Note deleted successfully.' }); + } catch (error) { + console.error('Error deleting note:', error); + res.status(400).json({ error: 'There was a problem deleting the note.' }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/projects.js b/backend/routes/projects.js new file mode 100644 index 0000000..c9781b2 --- /dev/null +++ b/backend/routes/projects.js @@ -0,0 +1,275 @@ +const express = require('express'); +const { Project, Task, Tag, Area, sequelize } = require('../models'); +const { Op } = require('sequelize'); +const router = express.Router(); + +// Helper function to update project tags +async function updateProjectTags(project, tagsData, userId) { + if (!tagsData) return; + + const tagNames = tagsData + .map(tag => tag.name) + .filter(name => name && name.trim()) + .filter((name, index, arr) => arr.indexOf(name) === index); // unique + + if (tagNames.length === 0) { + await project.setTags([]); + return; + } + + // Find existing tags + const existingTags = await Tag.findAll({ + where: { user_id: userId, name: tagNames } + }); + + // Create new tags + const existingTagNames = existingTags.map(tag => tag.name); + const newTagNames = tagNames.filter(name => !existingTagNames.includes(name)); + + const createdTags = await Promise.all( + newTagNames.map(name => Tag.create({ name, user_id: userId })) + ); + + // Set all tags to project + const allTags = [...existingTags, ...createdTags]; + await project.setTags(allTags); +} + +// GET /api/projects +router.get('/projects', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const { active, pin_to_sidebar, area_id } = req.query; + + let whereClause = { user_id: req.session.userId }; + + // Filter by active status + if (active === 'true') { + whereClause.active = true; + } else if (active === 'false') { + whereClause.active = false; + } + + // Filter by pinned status + if (pin_to_sidebar === 'true') { + whereClause.pin_to_sidebar = true; + } else if (pin_to_sidebar === 'false') { + whereClause.pin_to_sidebar = false; + } + + // Filter by area + if (area_id && area_id !== '') { + whereClause.area_id = area_id; + } + + const projects = await Project.findAll({ + where: whereClause, + include: [ + { + model: Task, + required: false, + attributes: ['id', 'status'] + }, + { + model: Area, + required: false, + attributes: ['name'] + }, + { + model: Tag, + attributes: ['id', 'name'], + through: { attributes: [] } + } + ], + order: [['name', 'ASC']] + }); + + // Calculate task status counts for each project + const taskStatusCounts = {}; + projects.forEach(project => { + const tasks = project.Tasks || []; + taskStatusCounts[project.id] = { + total: tasks.length, + done: tasks.filter(t => t.status === 2).length, + in_progress: tasks.filter(t => t.status === 1).length, + not_started: tasks.filter(t => t.status === 0).length + }; + }); + + // Group projects by area + const groupedProjects = {}; + projects.forEach(project => { + const areaName = project.Area ? project.Area.name : 'No Area'; + if (!groupedProjects[areaName]) { + groupedProjects[areaName] = []; + } + groupedProjects[areaName].push(project); + }); + + res.json({ + projects: projects.map(project => ({ + ...project.toJSON(), + due_date_at: project.due_date_at ? project.due_date_at.toISOString() : null + })), + task_status_counts: taskStatusCounts, + grouped_projects: groupedProjects + }); + } catch (error) { + console.error('Error fetching projects:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// GET /api/project/:id +router.get('/project/:id', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const project = await Project.findOne({ + where: { id: req.params.id, user_id: req.session.userId }, + include: [ + { model: Task, required: false }, + { model: Area, required: false, attributes: ['id', 'name'] }, + { model: Tag, attributes: ['id', 'name'], through: { attributes: [] } } + ] + }); + + if (!project) { + return res.status(404).json({ error: 'Project not found' }); + } + + res.json({ + ...project.toJSON(), + due_date_at: project.due_date_at ? project.due_date_at.toISOString() : null + }); + } catch (error) { + console.error('Error fetching project:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// POST /api/project +router.post('/project', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const { name, description, area_id, priority, due_date_at, tags } = req.body; + + if (!name || !name.trim()) { + return res.status(400).json({ error: 'Project name is required' }); + } + + const projectData = { + name: name.trim(), + description: description || '', + area_id: area_id || null, + active: true, + pin_to_sidebar: false, + priority: priority || null, + due_date_at: due_date_at || null, + user_id: req.session.userId + }; + + const project = await Project.create(projectData); + await updateProjectTags(project, tags, req.session.userId); + + // Reload project with associations + const projectWithAssociations = await Project.findByPk(project.id, { + include: [ + { model: Tag, attributes: ['id', 'name'], through: { attributes: [] } } + ] + }); + + res.status(201).json({ + ...projectWithAssociations.toJSON(), + due_date_at: projectWithAssociations.due_date_at ? projectWithAssociations.due_date_at.toISOString() : null + }); + } catch (error) { + console.error('Error creating project:', error); + res.status(400).json({ + error: 'There was a problem creating the project.', + details: error.errors ? error.errors.map(e => e.message) : [error.message] + }); + } +}); + +// PATCH /api/project/:id +router.patch('/project/:id', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const project = await Project.findOne({ + where: { id: req.params.id, user_id: req.session.userId } + }); + + if (!project) { + return res.status(404).json({ error: 'Project not found.' }); + } + + const { name, description, area_id, active, pin_to_sidebar, priority, due_date_at, tags } = req.body; + + const updateData = {}; + if (name !== undefined) updateData.name = name; + if (description !== undefined) updateData.description = description; + if (area_id !== undefined) updateData.area_id = area_id; + if (active !== undefined) updateData.active = active; + if (pin_to_sidebar !== undefined) updateData.pin_to_sidebar = pin_to_sidebar; + if (priority !== undefined) updateData.priority = priority; + if (due_date_at !== undefined) updateData.due_date_at = due_date_at; + + await project.update(updateData); + await updateProjectTags(project, tags, req.session.userId); + + // Reload project with associations + const projectWithAssociations = await Project.findByPk(project.id, { + include: [ + { model: Tag, attributes: ['id', 'name'], through: { attributes: [] } } + ] + }); + + res.json({ + ...projectWithAssociations.toJSON(), + due_date_at: projectWithAssociations.due_date_at ? projectWithAssociations.due_date_at.toISOString() : null + }); + } catch (error) { + console.error('Error updating project:', error); + res.status(400).json({ + error: 'There was a problem updating the project.', + details: error.errors ? error.errors.map(e => e.message) : [error.message] + }); + } +}); + +// DELETE /api/project/:id +router.delete('/project/:id', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const project = await Project.findOne({ + where: { id: req.params.id, user_id: req.session.userId } + }); + + if (!project) { + return res.status(404).json({ error: 'Project not found.' }); + } + + await project.destroy(); + res.json({ message: 'Project successfully deleted' }); + } catch (error) { + console.error('Error deleting project:', error); + res.status(400).json({ error: 'There was a problem deleting the project.' }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/quotes.js b/backend/routes/quotes.js new file mode 100644 index 0000000..f596909 --- /dev/null +++ b/backend/routes/quotes.js @@ -0,0 +1,30 @@ +const express = require('express'); +const router = express.Router(); +const quotesService = require('../services/quotesService'); + +// GET /api/quotes/random - Get a random quote +router.get('/quotes/random', (req, res) => { + try { + const quote = quotesService.getRandomQuote(); + res.json({ quote }); + } catch (error) { + console.error('Error getting random quote:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// GET /api/quotes - Get all quotes +router.get('/quotes', (req, res) => { + try { + const quotes = quotesService.getAllQuotes(); + res.json({ + quotes, + count: quotesService.getQuotesCount() + }); + } catch (error) { + console.error('Error getting quotes:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/tags.js b/backend/routes/tags.js new file mode 100644 index 0000000..a1f0b2e --- /dev/null +++ b/backend/routes/tags.js @@ -0,0 +1,132 @@ +const express = require('express'); +const { Tag } = require('../models'); +const router = express.Router(); + +// GET /api/tags +router.get('/tags', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const tags = await Tag.findAll({ + where: { user_id: req.session.userId }, + attributes: ['id', 'name'], + order: [['name', 'ASC']] + }); + + res.json(tags); + } catch (error) { + console.error('Error fetching tags:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// GET /api/tag/:id +router.get('/tag/:id', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const tag = await Tag.findOne({ + where: { id: req.params.id, user_id: req.session.userId }, + attributes: ['id', 'name'] + }); + + if (!tag) { + return res.status(404).json({ error: 'Tag not found' }); + } + + res.json(tag); + } catch (error) { + console.error('Error fetching tag:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// POST /api/tag +router.post('/tag', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const { name } = req.body; + + if (!name || !name.trim()) { + return res.status(400).json({ error: 'Tag name is required' }); + } + + const tag = await Tag.create({ + name: name.trim(), + user_id: req.session.userId + }); + + res.status(201).json({ + id: tag.id, + name: tag.name + }); + } catch (error) { + console.error('Error creating tag:', error); + res.status(400).json({ error: 'There was a problem creating the tag.' }); + } +}); + +// PATCH /api/tag/:id +router.patch('/tag/:id', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const tag = await Tag.findOne({ + where: { id: req.params.id, user_id: req.session.userId } + }); + + if (!tag) { + return res.status(404).json({ error: 'Tag not found' }); + } + + const { name } = req.body; + + if (!name || !name.trim()) { + return res.status(400).json({ error: 'Tag name is required' }); + } + + await tag.update({ name: name.trim() }); + + res.json({ + id: tag.id, + name: tag.name + }); + } catch (error) { + console.error('Error updating tag:', error); + res.status(400).json({ error: 'There was a problem updating the tag.' }); + } +}); + +// DELETE /api/tag/:id +router.delete('/tag/:id', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const tag = await Tag.findOne({ + where: { id: req.params.id, user_id: req.session.userId } + }); + + if (!tag) { + return res.status(404).json({ error: 'Tag not found' }); + } + + await tag.destroy(); + res.json({ message: 'Tag successfully deleted' }); + } catch (error) { + console.error('Error deleting tag:', error); + res.status(400).json({ error: 'There was a problem deleting the tag.' }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/tasks.js b/backend/routes/tasks.js new file mode 100644 index 0000000..6a1a9e1 --- /dev/null +++ b/backend/routes/tasks.js @@ -0,0 +1,394 @@ +const express = require('express'); +const { Task, Tag, Project, sequelize } = require('../models'); +const { Op } = require('sequelize'); +const router = express.Router(); + +// Helper function to update task tags +async function updateTaskTags(task, tagsData, userId) { + if (!tagsData) return; + + const tagNames = tagsData + .map(tag => tag.name) + .filter(name => name && name.trim()) + .filter((name, index, arr) => arr.indexOf(name) === index); // unique + + if (tagNames.length === 0) { + await task.setTags([]); + return; + } + + // Find existing tags + const existingTags = await Tag.findAll({ + where: { user_id: userId, name: tagNames } + }); + + // Create new tags + const existingTagNames = existingTags.map(tag => tag.name); + const newTagNames = tagNames.filter(name => !existingTagNames.includes(name)); + + const createdTags = await Promise.all( + newTagNames.map(name => Tag.create({ name, user_id: userId })) + ); + + // Set all tags to task + const allTags = [...existingTags, ...createdTags]; + await task.setTags(allTags); +} + +// Filter tasks by parameters +async function filterTasksByParams(params, userId) { + let whereClause = { user_id: userId }; + let includeClause = [ + { model: Tag, attributes: ['id', 'name'], through: { attributes: [] } }, + { model: Project, attributes: ['name'], required: false } + ]; + + // Filter by type + switch (params.type) { + case 'today': + // Just user tasks, no additional filtering + break; + case 'upcoming': + whereClause.due_date = { + [Op.between]: [new Date(), new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)] + }; + whereClause.status = { [Op.ne]: Task.STATUS.DONE }; + break; + case 'next': + whereClause.due_date = null; + whereClause.project_id = null; + whereClause.status = { [Op.ne]: Task.STATUS.DONE }; + break; + case 'inbox': + whereClause[Op.or] = [ + { due_date: null }, + { project_id: null } + ]; + whereClause.status = { [Op.ne]: Task.STATUS.DONE }; + break; + case 'someday': + whereClause.due_date = null; + whereClause.status = { [Op.ne]: Task.STATUS.DONE }; + break; + case 'waiting': + whereClause.status = Task.STATUS.WAITING; + break; + default: + if (params.status === 'done') { + whereClause.status = Task.STATUS.DONE; + } else { + whereClause.status = { [Op.ne]: Task.STATUS.DONE }; + } + } + + // Filter by tag + if (params.tag) { + includeClause[0].where = { name: params.tag }; + includeClause[0].required = true; + } + + let orderClause = [['created_at', 'ASC']]; + + // Apply ordering + if (params.order_by) { + const [orderColumn, orderDirection = 'asc'] = params.order_by.split(':'); + const allowedColumns = ['created_at', 'updated_at', 'name', 'priority', 'status', 'due_date']; + + if (!allowedColumns.includes(orderColumn)) { + throw new Error('Invalid order column specified.'); + } + + if (orderColumn === 'due_date') { + orderClause = [ + [sequelize.literal('CASE WHEN due_date IS NULL THEN 1 ELSE 0 END'), 'ASC'], + ['due_date', orderDirection.toUpperCase()] + ]; + } else { + orderClause = [[orderColumn, orderDirection.toUpperCase()]]; + } + } + + return await Task.findAll({ + where: whereClause, + include: includeClause, + order: orderClause, + distinct: true + }); +} + +// Compute task metrics +async function computeTaskMetrics(userId) { + const totalOpenTasks = await Task.count({ + where: { user_id: userId, status: { [Op.ne]: Task.STATUS.DONE } } + }); + + const oneMonthAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000); + const tasksPendingOverMonth = await Task.count({ + where: { + user_id: userId, + status: { [Op.ne]: Task.STATUS.DONE }, + created_at: { [Op.lt]: oneMonthAgo } + } + }); + + const tasksInProgress = await Task.findAll({ + where: { + user_id: userId, + status: Task.STATUS.IN_PROGRESS + }, + include: [ + { model: Tag, attributes: ['id', 'name'], through: { attributes: [] } }, + { model: Project, attributes: ['name'], required: false } + ], + order: [['priority', 'DESC']] + }); + + const today = new Date(); + today.setHours(23, 59, 59, 999); + + const tasksDueToday = await Task.findAll({ + where: { + user_id: userId, + status: { [Op.ne]: Task.STATUS.DONE }, + [Op.or]: [ + { due_date: { [Op.lte]: today } }, + sequelize.literal(`EXISTS ( + SELECT 1 FROM projects + WHERE projects.id = Task.project_id + AND projects.due_date_at <= '${today.toISOString()}' + )`) + ] + }, + include: [ + { model: Tag, attributes: ['id', 'name'], through: { attributes: [] } }, + { model: Project, attributes: ['name'], required: false } + ] + }); + + // Get suggested tasks (simplified version) + const excludedTaskIds = [ + ...tasksInProgress.map(t => t.id), + ...tasksDueToday.map(t => t.id) + ]; + + const suggestedTasks = await Task.findAll({ + where: { + user_id: userId, + status: Task.STATUS.NOT_STARTED, + id: { [Op.notIn]: excludedTaskIds } + }, + include: [ + { model: Tag, attributes: ['id', 'name'], through: { attributes: [] } }, + { model: Project, attributes: ['name'], required: false } + ], + order: [['priority', 'DESC']], + limit: 10 + }); + + return { + total_open_tasks: totalOpenTasks, + tasks_pending_over_month: tasksPendingOverMonth, + tasks_in_progress_count: tasksInProgress.length, + tasks_in_progress: tasksInProgress, + tasks_due_today: tasksDueToday, + suggested_tasks: suggestedTasks + }; +} + +// GET /api/tasks +router.get('/tasks', async (req, res) => { + try { + const tasks = await filterTasksByParams(req.query, req.currentUser.id); + const metrics = await computeTaskMetrics(req.currentUser.id); + + res.json({ + tasks: tasks.map(task => ({ + ...task.toJSON(), + due_date: task.due_date ? task.due_date.toISOString().split('T')[0] : null + })), + metrics: { + total_open_tasks: metrics.total_open_tasks, + tasks_pending_over_month: metrics.tasks_pending_over_month, + tasks_in_progress_count: metrics.tasks_in_progress_count, + tasks_in_progress: metrics.tasks_in_progress.map(task => ({ + ...task.toJSON(), + due_date: task.due_date ? task.due_date.toISOString().split('T')[0] : null + })), + tasks_due_today: metrics.tasks_due_today.map(task => ({ + ...task.toJSON(), + due_date: task.due_date ? task.due_date.toISOString().split('T')[0] : null + })), + suggested_tasks: metrics.suggested_tasks.map(task => ({ + ...task.toJSON(), + due_date: task.due_date ? task.due_date.toISOString().split('T')[0] : null + })) + } + }); + } catch (error) { + console.error('Error fetching tasks:', error); + if (error.message === 'Invalid order column specified.') { + return res.status(400).json({ error: error.message }); + } + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// POST /api/task +router.post('/task', async (req, res) => { + try { + const { name, priority, due_date, status, note, project_id, tags } = req.body; + + // Validate required fields + if (!name || name.trim() === '') { + return res.status(400).json({ error: 'Task name is required.' }); + } + + const taskAttributes = { + name: name.trim(), + priority: priority || Task.PRIORITY.LOW, + due_date: due_date || null, + status: status || Task.STATUS.NOT_STARTED, + note, + user_id: req.currentUser.id + }; + + // Handle project assignment + if (project_id && project_id.toString().trim()) { + const project = await Project.findOne({ + where: { id: project_id, user_id: req.currentUser.id } + }); + if (!project) { + return res.status(400).json({ error: 'Invalid project.' }); + } + taskAttributes.project_id = project_id; + } + + const task = await Task.create(taskAttributes); + await updateTaskTags(task, tags, req.currentUser.id); + + // Reload task with associations + const taskWithAssociations = await Task.findByPk(task.id, { + include: [ + { model: Tag, attributes: ['name'], through: { attributes: [] } }, + { model: Project, attributes: ['name'], required: false } + ] + }); + + res.status(201).json({ + ...taskWithAssociations.toJSON(), + due_date: taskWithAssociations.due_date ? taskWithAssociations.due_date.toISOString().split('T')[0] : null + }); + } catch (error) { + console.error('Error creating task:', error); + res.status(400).json({ + error: 'There was a problem creating the task.', + details: error.errors ? error.errors.map(e => e.message) : [error.message] + }); + } +}); + +// PATCH /api/task/:id +router.patch('/task/:id', async (req, res) => { + try { + const { name, priority, status, note, due_date, project_id, tags } = req.body; + + const task = await Task.findOne({ + where: { id: req.params.id, user_id: req.currentUser.id } + }); + + if (!task) { + return res.status(404).json({ error: 'Task not found.' }); + } + + const taskAttributes = { + name, + priority, + status: status || Task.STATUS.NOT_STARTED, + note, + due_date: due_date || null + }; + + // Handle project assignment + if (project_id && project_id.toString().trim()) { + const project = await Project.findOne({ + where: { id: project_id, user_id: req.currentUser.id } + }); + if (!project) { + return res.status(400).json({ error: 'Invalid project.' }); + } + taskAttributes.project_id = project_id; + } else { + taskAttributes.project_id = null; + } + + await task.update(taskAttributes); + await updateTaskTags(task, tags, req.currentUser.id); + + // Reload task with associations + const taskWithAssociations = await Task.findByPk(task.id, { + include: [ + { model: Tag, attributes: ['name'], through: { attributes: [] } }, + { model: Project, attributes: ['name'], required: false } + ] + }); + + res.json({ + ...taskWithAssociations.toJSON(), + due_date: taskWithAssociations.due_date ? taskWithAssociations.due_date.toISOString().split('T')[0] : null + }); + } catch (error) { + console.error('Error updating task:', error); + res.status(400).json({ + error: 'There was a problem updating the task.', + details: error.errors ? error.errors.map(e => e.message) : [error.message] + }); + } +}); + +// PATCH /api/task/:id/toggle_completion +router.patch('/task/:id/toggle_completion', async (req, res) => { + try { + const task = await Task.findOne({ + where: { id: req.params.id, user_id: req.currentUser.id } + }); + + if (!task) { + return res.status(404).json({ error: 'Task not found.' }); + } + + const newStatus = task.status === Task.STATUS.DONE + ? (task.note ? Task.STATUS.IN_PROGRESS : Task.STATUS.NOT_STARTED) + : Task.STATUS.DONE; + + await task.update({ status: newStatus }); + + res.json({ + ...task.toJSON(), + due_date: task.due_date ? task.due_date.toISOString().split('T')[0] : null + }); + } catch (error) { + console.error('Error toggling task completion:', error); + res.status(422).json({ error: 'Unable to update task' }); + } +}); + +// DELETE /api/task/:id +router.delete('/task/:id', async (req, res) => { + try { + const task = await Task.findOne({ + where: { id: req.params.id, user_id: req.currentUser.id } + }); + + if (!task) { + return res.status(404).json({ error: 'Task not found.' }); + } + + await task.destroy(); + res.json({ message: 'Task successfully deleted' }); + } catch (error) { + console.error('Error deleting task:', error); + res.status(400).json({ error: 'There was a problem deleting the task.' }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/telegram.js b/backend/routes/telegram.js new file mode 100644 index 0000000..2a5cce3 --- /dev/null +++ b/backend/routes/telegram.js @@ -0,0 +1,113 @@ +const express = require('express'); +const { User } = require('../models'); +const TelegramPoller = require('../services/telegramPoller'); +const router = express.Router(); + +// POST /api/telegram/start-polling +router.post('/telegram/start-polling', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const user = await User.findByPk(req.session.userId); + if (!user || !user.telegram_bot_token) { + return res.status(400).json({ error: 'Telegram bot token not set.' }); + } + + const poller = TelegramPoller.getInstance(); + const success = await poller.addUser(user); + + if (success) { + res.json({ + success: true, + message: 'Telegram polling started', + status: poller.getStatus() + }); + } else { + res.status(500).json({ error: 'Failed to start Telegram polling.' }); + } + } catch (error) { + console.error('Error starting Telegram polling:', error); + res.status(500).json({ error: 'Failed to start Telegram polling.' }); + } +}); + +// POST /api/telegram/stop-polling +router.post('/telegram/stop-polling', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const poller = TelegramPoller.getInstance(); + const success = poller.removeUser(req.session.userId); + + res.json({ + success: true, + message: 'Telegram polling stopped', + status: poller.getStatus() + }); + } catch (error) { + console.error('Error stopping Telegram polling:', error); + res.status(500).json({ error: 'Failed to stop Telegram polling.' }); + } +}); + +// GET /api/telegram/polling-status +router.get('/telegram/polling-status', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const poller = TelegramPoller.getInstance(); + + res.json({ + success: true, + status: poller.getStatus() + }); + } catch (error) { + console.error('Error getting Telegram polling status:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// POST /api/telegram/setup +router.post('/telegram/setup', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const { token } = req.body; + + if (!token) { + return res.status(400).json({ error: 'Telegram bot token is required.' }); + } + + const user = await User.findByPk(req.session.userId); + if (!user) { + return res.status(404).json({ error: 'User not found.' }); + } + + // Basic token validation - check if it looks like a Telegram bot token + if (!/^\d+:[A-Za-z0-9_-]{35}$/.test(token)) { + return res.status(400).json({ error: 'Invalid Telegram bot token format.' }); + } + + // Update user's telegram bot token + await user.update({ telegram_bot_token: token }); + + res.json({ + success: true, + message: 'Telegram bot token updated successfully', + token: token + }); + } catch (error) { + console.error('Error setting up Telegram:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/url.js b/backend/routes/url.js new file mode 100644 index 0000000..b4edd6c --- /dev/null +++ b/backend/routes/url.js @@ -0,0 +1,156 @@ +const express = require('express'); +const https = require('https'); +const http = require('http'); +const { URL } = require('url'); +const router = express.Router(); + +// Helper function to extract title from HTML +function extractTitleFromHtml(html) { + const titleMatch = html.match(/]*>([^<]+)<\/title>/i); + if (titleMatch && titleMatch[1]) { + // Decode HTML entities and clean up + return titleMatch[1] + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, "'") + .trim(); + } + return null; +} + +// Helper function to check if text is a URL +function isUrl(text) { + const urlRegex = /^(https?:\/\/)?[a-z0-9]+([-.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/i; + return urlRegex.test(text.trim()); +} + +// Helper function to fetch URL title +async function fetchUrlTitle(url) { + return new Promise((resolve) => { + // Add protocol if missing + if (!url.startsWith('http://') && !url.startsWith('https://')) { + url = 'http://' + url; + } + + try { + const urlObj = new URL(url); + const isHttps = urlObj.protocol === 'https:'; + const client = isHttps ? https : http; + + const options = { + hostname: urlObj.hostname, + port: urlObj.port || (isHttps ? 443 : 80), + path: urlObj.pathname + urlObj.search, + method: 'GET', + timeout: 5000, + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' + } + }; + + const req = client.request(options, (res) => { + let data = ''; + let totalBytes = 0; + const maxBytes = 50000; + + res.on('data', (chunk) => { + totalBytes += chunk.length; + if (totalBytes > maxBytes) { + req.destroy(); + return; + } + data += chunk; + + // Stop if we find the title tag + if (data.includes('')) { + req.destroy(); + } + }); + + res.on('end', () => { + const title = extractTitleFromHtml(data); + resolve(title); + }); + }); + + req.on('error', () => { + resolve(null); + }); + + req.on('timeout', () => { + req.destroy(); + resolve(null); + }); + + req.end(); + } catch (error) { + resolve(null); + } + }); +} + +// GET /api/url/title +router.get('/url/title', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const { url } = req.query; + + if (!url) { + return res.status(400).json({ error: 'URL parameter is required' }); + } + + const title = await fetchUrlTitle(url); + + if (title) { + res.json({ url, title }); + } else { + res.json({ url, title: null, error: 'Could not extract title' }); + } + } catch (error) { + console.error('Error extracting URL title:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// POST /api/url/extract-from-text +router.post('/url/extract-from-text', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const { text } = req.body; + + if (!text) { + return res.status(400).json({ error: 'Text parameter is required' }); + } + + // Simple URL extraction - look for URLs in text + const urlRegex = /(https?:\/\/[^\s]+)/gi; + const urls = text.match(urlRegex); + + if (urls && urls.length > 0) { + const firstUrl = urls[0]; + const title = await fetchUrlTitle(firstUrl); + + res.json({ + found: true, + url: firstUrl, + title: title, + originalText: text + }); + } else { + res.json({ found: false }); + } + } catch (error) { + console.error('Error extracting URL from text:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/routes/users.js b/backend/routes/users.js new file mode 100644 index 0000000..24abfff --- /dev/null +++ b/backend/routes/users.js @@ -0,0 +1,206 @@ +const express = require('express'); +const { User } = require('../models'); +const TaskSummaryService = require('../services/taskSummaryService'); +const router = express.Router(); + +const VALID_FREQUENCIES = ['daily', 'weekdays', 'weekly', '1h', '2h', '4h', '8h', '12h']; + +// GET /api/profile +router.get('/profile', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const user = await User.findByPk(req.session.userId, { + attributes: [ + 'id', 'email', 'appearance', 'language', 'timezone', + 'avatar_image', 'telegram_bot_token', 'telegram_chat_id', + 'task_summary_enabled', 'task_summary_frequency' + ] + }); + + if (!user) { + return res.status(404).json({ error: 'Profile not found.' }); + } + + res.json(user); + } catch (error) { + console.error('Error fetching profile:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +// PATCH /api/profile +router.patch('/profile', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const user = await User.findByPk(req.session.userId); + if (!user) { + return res.status(404).json({ error: 'Profile not found.' }); + } + + const { appearance, language, timezone, avatar_image, telegram_bot_token } = req.body; + + const allowedUpdates = {}; + if (appearance !== undefined) allowedUpdates.appearance = appearance; + if (language !== undefined) allowedUpdates.language = language; + if (timezone !== undefined) allowedUpdates.timezone = timezone; + if (avatar_image !== undefined) allowedUpdates.avatar_image = avatar_image; + if (telegram_bot_token !== undefined) allowedUpdates.telegram_bot_token = telegram_bot_token; + + await user.update(allowedUpdates); + + // Return updated user with limited fields + const updatedUser = await User.findByPk(user.id, { + attributes: ['id', 'email', 'appearance', 'language', 'timezone', 'avatar_image', 'telegram_bot_token', 'telegram_chat_id'] + }); + + res.json(updatedUser); + } catch (error) { + console.error('Error updating profile:', error); + res.status(400).json({ + error: 'Failed to update profile.', + details: error.errors ? error.errors.map(e => e.message) : [error.message] + }); + } +}); + +// POST /api/profile/task-summary/toggle +router.post('/profile/task-summary/toggle', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const user = await User.findByPk(req.session.userId); + if (!user) { + return res.status(404).json({ error: 'User not found.' }); + } + + const enabled = !user.task_summary_enabled; + + await user.update({ task_summary_enabled: enabled }); + + // Note: Telegram integration would need to be implemented separately + const message = enabled + ? 'Task summary notifications have been enabled.' + : 'Task summary notifications have been disabled.'; + + res.json({ + success: true, + enabled: enabled, + message: message + }); + } catch (error) { + console.error('Error toggling task summary:', error); + res.status(400).json({ + error: 'Failed to update task summary settings.', + details: error.errors ? error.errors.map(e => e.message) : [error.message] + }); + } +}); + +// POST /api/profile/task-summary/frequency +router.post('/profile/task-summary/frequency', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const { frequency } = req.body; + + if (!frequency) { + return res.status(400).json({ error: 'Frequency is required.' }); + } + + if (!VALID_FREQUENCIES.includes(frequency)) { + return res.status(400).json({ error: 'Invalid frequency value.' }); + } + + const user = await User.findByPk(req.session.userId); + if (!user) { + return res.status(404).json({ error: 'User not found.' }); + } + + await user.update({ task_summary_frequency: frequency }); + + res.json({ + success: true, + frequency: frequency, + message: `Task summary frequency has been set to ${frequency}.` + }); + } catch (error) { + console.error('Error updating task summary frequency:', error); + res.status(400).json({ + error: 'Failed to update task summary frequency.', + details: error.errors ? error.errors.map(e => e.message) : [error.message] + }); + } +}); + +// POST /api/profile/task-summary/send-now +router.post('/profile/task-summary/send-now', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const user = await User.findByPk(req.session.userId); + if (!user) { + return res.status(404).json({ error: 'User not found.' }); + } + + if (!user.telegram_bot_token || !user.telegram_chat_id) { + return res.status(400).json({ error: 'Telegram bot is not properly configured.' }); + } + + // Send the task summary + const success = await TaskSummaryService.sendSummaryToUser(user.id); + + if (success) { + res.json({ + success: true, + message: 'Task summary was sent to your Telegram.' + }); + } else { + res.status(400).json({ error: 'Failed to send message to Telegram.' }); + } + } catch (error) { + console.error('Error sending task summary:', error); + res.status(400).json({ + error: 'Error sending message to Telegram.', + details: error.message + }); + } +}); + +// GET /api/profile/task-summary/status +router.get('/profile/task-summary/status', async (req, res) => { + try { + if (!req.session || !req.session.userId) { + return res.status(401).json({ error: 'Authentication required' }); + } + + const user = await User.findByPk(req.session.userId); + if (!user) { + return res.status(404).json({ error: 'User not found.' }); + } + + res.json({ + success: true, + enabled: user.task_summary_enabled, + frequency: user.task_summary_frequency, + last_run: user.task_summary_last_run, + next_run: user.task_summary_next_run + }); + } catch (error) { + console.error('Error fetching task summary status:', error); + res.status(500).json({ error: 'Internal server error' }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/backend/scripts/db-init.js b/backend/scripts/db-init.js new file mode 100755 index 0000000..734630c --- /dev/null +++ b/backend/scripts/db-init.js @@ -0,0 +1,27 @@ +#!/usr/bin/env node + +/** + * Database Initialization Script + * Initializes the database by creating all tables and dropping existing data + */ + +require('dotenv').config(); +const { sequelize } = require('../models'); + +async function initDatabase() { + try { + console.log('Initializing database...'); + console.log('WARNING: This will drop all existing data!'); + + await sequelize.sync({ force: true }); + + console.log('✅ Database initialized successfully'); + console.log('All tables have been created and existing data has been cleared'); + process.exit(0); + } catch (error) { + console.error('❌ Error initializing database:', error.message); + process.exit(1); + } +} + +initDatabase(); \ No newline at end of file diff --git a/backend/scripts/db-migrate.js b/backend/scripts/db-migrate.js new file mode 100755 index 0000000..d23c5fc --- /dev/null +++ b/backend/scripts/db-migrate.js @@ -0,0 +1,27 @@ +#!/usr/bin/env node + +/** + * Database Migration Script + * Migrates the database by altering existing tables to match current models + */ + +require('dotenv').config(); +const { sequelize } = require('../models'); + +async function migrateDatabase() { + try { + console.log('Migrating database...'); + console.log('This will alter existing tables to match current models'); + + await sequelize.sync({ alter: true }); + + console.log('✅ Database migrated successfully'); + console.log('All tables have been updated to match current models'); + process.exit(0); + } catch (error) { + console.error('❌ Error migrating database:', error.message); + process.exit(1); + } +} + +migrateDatabase(); \ No newline at end of file diff --git a/backend/scripts/db-reset.js b/backend/scripts/db-reset.js new file mode 100755 index 0000000..dddd7cf --- /dev/null +++ b/backend/scripts/db-reset.js @@ -0,0 +1,27 @@ +#!/usr/bin/env node + +/** + * Database Reset Script + * Resets the database by dropping and recreating all tables + */ + +require('dotenv').config(); +const { sequelize } = require('../models'); + +async function resetDatabase() { + try { + console.log('Resetting database...'); + console.log('WARNING: This will permanently delete all data!'); + + await sequelize.sync({ force: true }); + + console.log('✅ Database reset successfully'); + console.log('All tables have been dropped and recreated'); + process.exit(0); + } catch (error) { + console.error('❌ Error resetting database:', error.message); + process.exit(1); + } +} + +resetDatabase(); \ No newline at end of file diff --git a/backend/scripts/db-status.js b/backend/scripts/db-status.js new file mode 100755 index 0000000..131ca93 --- /dev/null +++ b/backend/scripts/db-status.js @@ -0,0 +1,69 @@ +#!/usr/bin/env node + +/** + * Database Status Script + * Shows database connection status and basic information + */ + +require('dotenv').config(); +const { sequelize, User, Task, Project, Area, Note, Tag, InboxItem } = require('../models'); +const fs = require('fs'); +const path = require('path'); + +async function checkDatabaseStatus() { + try { + console.log('🔍 Checking database status...\n'); + + // Check database file + const dbConfig = sequelize.config || sequelize.options; + const dbPath = dbConfig.storage || sequelize.options.storage; + + console.log('📂 Database Configuration:'); + console.log(` Storage: ${dbPath}`); + console.log(` Dialect: ${dbConfig.dialect || sequelize.options.dialect || 'sqlite'}`); + console.log(` Environment: ${process.env.NODE_ENV || 'development'}`); + + // Check if database file exists + if (fs.existsSync(dbPath)) { + const stats = fs.statSync(dbPath); + console.log(` File size: ${(stats.size / 1024).toFixed(2)} KB`); + console.log(` Last modified: ${stats.mtime.toISOString()}`); + } else { + console.log(' ⚠️ Database file does not exist'); + } + + console.log('\n🔌 Testing database connection...'); + await sequelize.authenticate(); + console.log('✅ Database connection successful\n'); + + // Get table information + console.log('📊 Table Statistics:'); + const models = [ + { name: 'Users', model: User }, + { name: 'Areas', model: Area }, + { name: 'Projects', model: Project }, + { name: 'Tasks', model: Task }, + { name: 'Notes', model: Note }, + { name: 'Tags', model: Tag }, + { name: 'Inbox Items', model: InboxItem } + ]; + + for (const { name, model } of models) { + try { + const count = await model.count(); + console.log(` ${name}: ${count} records`); + } catch (error) { + console.log(` ${name}: ❌ Error (${error.message})`); + } + } + + console.log('\n✅ Database status check completed'); + process.exit(0); + } catch (error) { + console.error('\n❌ Database connection failed:', error.message); + console.error('\n💡 Try running: npm run db:init'); + process.exit(1); + } +} + +checkDatabaseStatus(); \ No newline at end of file diff --git a/backend/scripts/db-sync.js b/backend/scripts/db-sync.js new file mode 100755 index 0000000..81ca901 --- /dev/null +++ b/backend/scripts/db-sync.js @@ -0,0 +1,26 @@ +#!/usr/bin/env node + +/** + * Database Sync Script + * Syncs the database by creating tables if they don't exist (without dropping existing data) + */ + +require('dotenv').config(); +const { sequelize } = require('../models'); + +async function syncDatabase() { + try { + console.log('Syncing database...'); + + await sequelize.sync(); + + console.log('✅ Database synchronized successfully'); + console.log('All tables have been created (existing data preserved)'); + process.exit(0); + } catch (error) { + console.error('❌ Error syncing database:', error.message); + process.exit(1); + } +} + +syncDatabase(); \ No newline at end of file diff --git a/backend/scripts/migration-create.js b/backend/scripts/migration-create.js new file mode 100755 index 0000000..64e4e9a --- /dev/null +++ b/backend/scripts/migration-create.js @@ -0,0 +1,108 @@ +#!/usr/bin/env node + +/** + * Migration Creation Script + * Creates a new Sequelize migration file + * Usage: node scripts/migration-create.js + */ + +const fs = require('fs'); +const path = require('path'); + +function createMigration() { + const migrationName = process.argv[2]; + + if (!migrationName) { + console.error('❌ Usage: npm run migration:create '); + console.error('Example: npm run migration:create add-description-to-tasks'); + process.exit(1); + } + + // Generate timestamp (YYYYMMDDHHMMSS format) + const now = new Date(); + const timestamp = now.getFullYear().toString() + + (now.getMonth() + 1).toString().padStart(2, '0') + + now.getDate().toString().padStart(2, '0') + + now.getHours().toString().padStart(2, '0') + + now.getMinutes().toString().padStart(2, '0') + + now.getSeconds().toString().padStart(2, '0'); + + const fileName = `${timestamp}-${migrationName}.js`; + const filePath = path.join(__dirname, '..', 'migrations', fileName); + + // Migration template + const template = `'use strict'; + +module.exports = { + async up(queryInterface, Sequelize) { + // Add your migration logic here + // Examples: + + // Add a new column: + // await queryInterface.addColumn('table_name', 'column_name', { + // type: Sequelize.STRING, + // allowNull: true + // }); + + // Create a new table: + // await queryInterface.createTable('table_name', { + // id: { + // allowNull: false, + // autoIncrement: true, + // primaryKey: true, + // type: Sequelize.INTEGER + // }, + // created_at: { + // allowNull: false, + // type: Sequelize.DATE, + // defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + // }, + // updated_at: { + // allowNull: false, + // type: Sequelize.DATE, + // defaultValue: Sequelize.literal('CURRENT_TIMESTAMP') + // } + // }); + + // Add an index: + // await queryInterface.addIndex('table_name', ['column_name']); + + throw new Error('Migration not implemented yet!'); + }, + + async down(queryInterface, Sequelize) { + // Add your rollback logic here + // Examples: + + // Remove a column: + // await queryInterface.removeColumn('table_name', 'column_name'); + + // Drop a table: + // await queryInterface.dropTable('table_name'); + + // Remove an index: + // await queryInterface.removeIndex('table_name', ['column_name']); + + throw new Error('Rollback not implemented yet!'); + } +};`; + + try { + fs.writeFileSync(filePath, template); + console.log('✅ Migration created successfully'); + console.log(`📁 File: ${fileName}`); + console.log(`📂 Path: ${filePath}`); + console.log(''); + console.log('📝 Next steps:'); + console.log('1. Edit the migration file to add your schema changes'); + console.log('2. Run: npm run migration:run'); + console.log('3. To rollback: npm run migration:undo'); + + process.exit(0); + } catch (error) { + console.error('❌ Error creating migration:', error.message); + process.exit(1); + } +} + +createMigration(); \ No newline at end of file diff --git a/backend/scripts/user-create.js b/backend/scripts/user-create.js new file mode 100755 index 0000000..8ebe3a1 --- /dev/null +++ b/backend/scripts/user-create.js @@ -0,0 +1,66 @@ +#!/usr/bin/env node + +/** + * User Creation Script + * Creates a new user with email and password + * Usage: node user-create.js + */ + +require('dotenv').config(); +const { User } = require('../models'); +const bcrypt = require('bcrypt'); + +async function createUser() { + const [email, password] = process.argv.slice(2); + + if (!email || !password) { + console.error('❌ Usage: npm run user:create '); + console.error('Example: npm run user:create admin@example.com mypassword123'); + process.exit(1); + } + + // Basic email validation + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + if (!emailRegex.test(email)) { + console.error('❌ Invalid email format'); + process.exit(1); + } + + // Basic password validation + if (password.length < 6) { + console.error('❌ Password must be at least 6 characters long'); + process.exit(1); + } + + try { + console.log(`Creating user with email: ${email}`); + + // Check if user already exists + const existingUser = await User.findOne({ where: { email } }); + if (existingUser) { + console.error(`❌ User with email ${email} already exists`); + process.exit(1); + } + + // Hash the password + const hashedPassword = await bcrypt.hash(password, 10); + + // Create the user + const user = await User.create({ + email, + password: hashedPassword + }); + + console.log('✅ User created successfully'); + console.log(`📧 Email: ${user.email}`); + console.log(`🆔 User ID: ${user.id}`); + console.log(`📅 Created: ${user.created_at}`); + + process.exit(0); + } catch (error) { + console.error('❌ Error creating user:', error.message); + process.exit(1); + } +} + +createUser(); \ No newline at end of file diff --git a/backend/services/quotesService.js b/backend/services/quotesService.js new file mode 100644 index 0000000..0b1bdf2 --- /dev/null +++ b/backend/services/quotesService.js @@ -0,0 +1,65 @@ +const fs = require('fs'); +const path = require('path'); +const yaml = require('js-yaml'); + +class QuotesService { + constructor() { + this.quotes = []; + this.loadQuotes(); + } + + loadQuotes() { + try { + const quotesPath = path.join(__dirname, '../config/quotes.yml'); + + if (fs.existsSync(quotesPath)) { + const fileContents = fs.readFileSync(quotesPath, 'utf8'); + const data = yaml.load(fileContents); + + if (data && data.quotes && Array.isArray(data.quotes)) { + this.quotes = data.quotes; + console.log(`Loaded ${this.quotes.length} quotes from configuration`); + } else { + console.warn('No quotes found in configuration file'); + this.setDefaultQuotes(); + } + } else { + console.warn('Quotes configuration file not found, using defaults'); + this.setDefaultQuotes(); + } + } catch (error) { + console.error('Error loading quotes:', error.message); + this.setDefaultQuotes(); + } + } + + setDefaultQuotes() { + this.quotes = [ + "Believe you can and you're halfway there.", + "The only way to do great work is to love what you do.", + "It always seems impossible until it's done.", + "Focus on progress, not perfection.", + "One task at a time leads to great accomplishments." + ]; + } + + getRandomQuote() { + if (this.quotes.length === 0) { + return "Stay focused and keep going!"; + } + + const randomIndex = Math.floor(Math.random() * this.quotes.length); + return this.quotes[randomIndex]; + } + + getAllQuotes() { + return this.quotes; + } + + getQuotesCount() { + return this.quotes.length; + } +} + +// Export singleton instance +module.exports = new QuotesService(); \ No newline at end of file diff --git a/backend/services/taskScheduler.js b/backend/services/taskScheduler.js new file mode 100644 index 0000000..7d24281 --- /dev/null +++ b/backend/services/taskScheduler.js @@ -0,0 +1,181 @@ +const cron = require('node-cron'); +const { User } = require('../models'); +const TaskSummaryService = require('./taskSummaryService'); + +class TaskScheduler { + constructor() { + this.jobs = new Map(); + this.isInitialized = false; + } + + static getInstance() { + if (!TaskScheduler.instance) { + TaskScheduler.instance = new TaskScheduler(); + } + return TaskScheduler.instance; + } + + async initialize() { + if (this.isInitialized) { + console.log('Task scheduler already initialized'); + return; + } + + // Don't schedule in test environment + if (process.env.NODE_ENV === 'test' || process.env.DISABLE_SCHEDULER === 'true') { + console.log('Task scheduler disabled for test environment'); + return; + } + + console.log('Initializing task scheduler...'); + + // Daily schedule at 7 AM (for users with daily frequency) + const dailyJob = cron.schedule('0 7 * * *', async () => { + console.log('Running scheduled task: Daily task summary'); + await this.processSummariesForFrequency('daily'); + }, { + scheduled: false, + timezone: 'UTC' + }); + + // Weekdays schedule at 7 AM (Monday through Friday) + const weekdaysJob = cron.schedule('0 7 * * 1-5', async () => { + console.log('Running scheduled task: Weekday task summary'); + await this.processSummariesForFrequency('weekdays'); + }, { + scheduled: false, + timezone: 'UTC' + }); + + // Weekly schedule at 7 AM on Monday + const weeklyJob = cron.schedule('0 7 * * 1', async () => { + console.log('Running scheduled task: Weekly task summary'); + await this.processSummariesForFrequency('weekly'); + }, { + scheduled: false, + timezone: 'UTC' + }); + + // Hourly schedules + const hourlyJob = cron.schedule('0 * * * *', async () => { + console.log('Running scheduled task: Hourly (1h) task summary'); + await this.processSummariesForFrequency('1h'); + }, { + scheduled: false, + timezone: 'UTC' + }); + + const twoHourlyJob = cron.schedule('0 */2 * * *', async () => { + console.log('Running scheduled task: 2-hour task summary'); + await this.processSummariesForFrequency('2h'); + }, { + scheduled: false, + timezone: 'UTC' + }); + + const fourHourlyJob = cron.schedule('0 */4 * * *', async () => { + console.log('Running scheduled task: 4-hour task summary'); + await this.processSummariesForFrequency('4h'); + }, { + scheduled: false, + timezone: 'UTC' + }); + + const eightHourlyJob = cron.schedule('0 */8 * * *', async () => { + console.log('Running scheduled task: 8-hour task summary'); + await this.processSummariesForFrequency('8h'); + }, { + scheduled: false, + timezone: 'UTC' + }); + + const twelveHourlyJob = cron.schedule('0 */12 * * *', async () => { + console.log('Running scheduled task: 12-hour task summary'); + await this.processSummariesForFrequency('12h'); + }, { + scheduled: false, + timezone: 'UTC' + }); + + // Store jobs for later management + this.jobs.set('daily', dailyJob); + this.jobs.set('weekdays', weekdaysJob); + this.jobs.set('weekly', weeklyJob); + this.jobs.set('1h', hourlyJob); + this.jobs.set('2h', twoHourlyJob); + this.jobs.set('4h', fourHourlyJob); + this.jobs.set('8h', eightHourlyJob); + this.jobs.set('12h', twelveHourlyJob); + + // Start all jobs + this.jobs.forEach((job, frequency) => { + job.start(); + console.log(`Started scheduler for frequency: ${frequency}`); + }); + + this.isInitialized = true; + console.log('Task scheduler initialized successfully'); + } + + async processSummariesForFrequency(frequency) { + try { + const users = await User.findAll({ + where: { + telegram_bot_token: { [require('sequelize').Op.ne]: null }, + telegram_chat_id: { [require('sequelize').Op.ne]: null }, + task_summary_enabled: true, + task_summary_frequency: frequency + } + }); + + console.log(`Processing ${users.length} users for frequency: ${frequency}`); + + for (const user of users) { + try { + const success = await TaskSummaryService.sendSummaryToUser(user.id); + if (success) { + console.log(`Sent ${frequency} summary to user ${user.id}`); + } else { + console.log(`Failed to send ${frequency} summary to user ${user.id}`); + } + } catch (error) { + console.error(`Error sending ${frequency} summary to user ${user.id}:`, error.message); + } + } + } catch (error) { + console.error(`Error processing summaries for frequency ${frequency}:`, error); + } + } + + async stop() { + if (!this.isInitialized) { + console.log('Task scheduler not initialized, nothing to stop'); + return; + } + + console.log('Stopping task scheduler...'); + this.jobs.forEach((job, frequency) => { + job.stop(); + console.log(`Stopped scheduler for frequency: ${frequency}`); + }); + + this.jobs.clear(); + this.isInitialized = false; + console.log('Task scheduler stopped'); + } + + async restart() { + await this.stop(); + await this.initialize(); + } + + getStatus() { + return { + initialized: this.isInitialized, + jobCount: this.jobs.size, + jobs: Array.from(this.jobs.keys()) + }; + } +} + +module.exports = TaskScheduler; \ No newline at end of file diff --git a/backend/services/taskSummaryService.js b/backend/services/taskSummaryService.js new file mode 100644 index 0000000..07e05c5 --- /dev/null +++ b/backend/services/taskSummaryService.js @@ -0,0 +1,238 @@ +const { User, Task, Project, Tag } = require('../models'); +const { Op } = require('sequelize'); +const TelegramPoller = require('./telegramPoller'); + +class TaskSummaryService { + // Helper method to escape special characters for MarkdownV2 + static escapeMarkdown(text) { + if (!text) return ''; + // Characters that need to be escaped in MarkdownV2: _*[]()~`>#+-=|{}.! + return text.toString().replace(/([_*\[\]()~`>#+\-=|{}.!])/g, '\\$1'); + } + + static async generateSummaryForUser(userId) { + try { + const user = await User.findByPk(userId); + if (!user) return null; + + // Get today's date + const today = new Date(); + today.setHours(0, 0, 0, 0); + const tomorrow = new Date(today); + tomorrow.setDate(tomorrow.getDate() + 1); + + // Get today's tasks, in progress tasks, etc. + const dueToday = await Task.findAll({ + where: { + user_id: userId, + due_date: { + [Op.gte]: today, + [Op.lt]: tomorrow + }, + status: { [Op.ne]: 2 } // not done + }, + include: [{ model: Project, attributes: ['name'] }], + order: [['name', 'ASC']] + }); + + const inProgress = await Task.findAll({ + where: { + user_id: userId, + status: 1 // in_progress + }, + include: [{ model: Project, attributes: ['name'] }], + order: [['name', 'ASC']] + }); + + const completedToday = await Task.findAll({ + where: { + user_id: userId, + status: 2, // done + updated_at: { + [Op.gte]: today, + [Op.lt]: tomorrow + } + }, + include: [{ model: Project, attributes: ['name'] }], + order: [['name', 'ASC']] + }); + + // Generate summary message + let message = "📋 *Today's Task Summary*\n\n"; + message += "━━━━━━━━━━━━━━━━━━━━━━━━\n\n"; + message += "✏️ *Today's Plan*\n\n"; + + // Add due today tasks + if (dueToday.length > 0) { + message += "🚀 *Tasks Due Today:*\n"; + dueToday.forEach((task, index) => { + const priorityEmoji = this.getPriorityEmoji(task.priority); + const taskName = this.escapeMarkdown(task.name); + const projectInfo = task.Project ? ` \\[${this.escapeMarkdown(task.Project.name)}\\]` : ''; + message += `${index + 1}\\. ${priorityEmoji} ${taskName}${projectInfo}\n`; + }); + message += "\n"; + } + + // Add in progress tasks + if (inProgress.length > 0) { + message += "⚙️ *In Progress Tasks:*\n"; + inProgress.forEach((task, index) => { + const priorityEmoji = this.getPriorityEmoji(task.priority); + const taskName = this.escapeMarkdown(task.name); + const projectInfo = task.Project ? ` \\[${this.escapeMarkdown(task.Project.name)}\\]` : ''; + message += `${index + 1}\\. ${priorityEmoji} ${taskName}${projectInfo}\n`; + }); + message += "\n"; + } + + // Get suggested tasks (not done, not in due today or in progress) + const excludedIds = [...dueToday.map(t => t.id), ...inProgress.map(t => t.id)]; + + const suggestedTasks = await Task.findAll({ + where: { + user_id: userId, + status: { [Op.ne]: 2 }, // not done + id: { [Op.notIn]: excludedIds } + }, + include: [{ model: Project, attributes: ['name'] }], + order: [['priority', 'DESC'], ['name', 'ASC']], + limit: 5 + }); + + if (suggestedTasks.length > 0) { + message += "💡 *Suggested Tasks:*\n"; + suggestedTasks.forEach((task, index) => { + const priorityEmoji = this.getPriorityEmoji(task.priority); + const taskName = this.escapeMarkdown(task.name); + const projectInfo = task.Project ? ` \\[${this.escapeMarkdown(task.Project.name)}\\]` : ''; + message += `${index + 1}\\. ${priorityEmoji} ${taskName}${projectInfo}\n`; + }); + message += "\n"; + } + + // Add completed tasks + if (completedToday.length > 0) { + message += "✅ *Completed Today:*\n"; + completedToday.forEach((task, index) => { + const taskName = this.escapeMarkdown(task.name); + const projectInfo = task.Project ? ` \\[${this.escapeMarkdown(task.Project.name)}\\]` : ''; + message += `${index + 1}\\. ✅ ${taskName}${projectInfo}\n`; + }); + message += "\n"; + } + + // Add footer + message += "━━━━━━━━━━━━━━━━━━━━━━━━\n"; + message += "🎯 *Stay focused and make it happen\\!*"; + + return message; + } catch (error) { + console.error('Error generating task summary:', error); + return null; + } + } + + static getPriorityEmoji(priority) { + switch (priority) { + case 2: return '🔴'; // high + case 1: return '🟠'; // medium + case 0: return '🟢'; // low + default: return '⚪'; + } + } + + static async sendSummaryToUser(userId) { + try { + const user = await User.findByPk(userId); + if (!user || !user.telegram_bot_token || !user.telegram_chat_id) { + return false; + } + + const summary = await this.generateSummaryForUser(userId); + if (!summary) return false; + + // Send the message via Telegram + const poller = TelegramPoller.getInstance(); + await poller.sendTelegramMessage( + user.telegram_bot_token, + user.telegram_chat_id, + summary + ); + + // Update the last run time and calculate the next run time + const now = new Date(); + const nextRun = this.calculateNextRunTime(user, now); + + // Update the user's tracking fields + await user.update({ + task_summary_last_run: now, + task_summary_next_run: nextRun + }); + + return true; + } catch (error) { + console.error(`Error sending task summary to user ${userId}:`, error.message); + return false; + } + } + + static calculateNextRunTime(user, fromTime = new Date()) { + const frequency = user.task_summary_frequency; + const from = new Date(fromTime); + + switch (frequency) { + case 'daily': + // Next day at 7 AM + const nextDay = new Date(from); + nextDay.setDate(nextDay.getDate() + 1); + nextDay.setHours(7, 0, 0, 0); + return nextDay; + + case 'weekdays': + // Next weekday at 7 AM + const currentDay = from.getDay(); // 0 = Sunday, 1 = Monday, ..., 6 = Saturday + let daysToAdd = 1; + if (currentDay === 5) { // Friday + daysToAdd = 3; // Skip to Monday + } else if (currentDay === 6) { // Saturday + daysToAdd = 2; // Skip to Monday + } + const nextWeekday = new Date(from); + nextWeekday.setDate(nextWeekday.getDate() + daysToAdd); + nextWeekday.setHours(7, 0, 0, 0); + return nextWeekday; + + case 'weekly': + // Next Monday at 7 AM + const nextWeek = new Date(from); + nextWeek.setDate(nextWeek.getDate() + 7); + nextWeek.setHours(7, 0, 0, 0); + return nextWeek; + + case '1h': + return new Date(from.getTime() + 60 * 60 * 1000); + + case '2h': + return new Date(from.getTime() + 2 * 60 * 60 * 1000); + + case '4h': + return new Date(from.getTime() + 4 * 60 * 60 * 1000); + + case '8h': + return new Date(from.getTime() + 8 * 60 * 60 * 1000); + + case '12h': + return new Date(from.getTime() + 12 * 60 * 60 * 1000); + + default: + // Default to daily + const defaultNext = new Date(from); + defaultNext.setDate(defaultNext.getDate() + 1); + defaultNext.setHours(7, 0, 0, 0); + return defaultNext; + } + } +} + +module.exports = TaskSummaryService; \ No newline at end of file diff --git a/backend/services/telegramInitializer.js b/backend/services/telegramInitializer.js new file mode 100644 index 0000000..07b9ed0 --- /dev/null +++ b/backend/services/telegramInitializer.js @@ -0,0 +1,43 @@ +const TelegramPoller = require('./telegramPoller'); +const { User } = require('../models'); + +async function initializeTelegramPolling() { + if (process.env.NODE_ENV === 'test' || process.env.DISABLE_TELEGRAM === 'true') { + return; + } + + console.log('Initializing Telegram polling for configured users...'); + + try { + // Get singleton instance of the poller + const poller = TelegramPoller.getInstance(); + + // Find users with configured Telegram tokens + const usersWithTelegram = await User.findAll({ + where: { + telegram_bot_token: { + [require('sequelize').Op.ne]: null + } + } + }); + + if (usersWithTelegram.length > 0) { + console.log(`Found ${usersWithTelegram.length} users with Telegram configuration`); + + // Add each user to the polling list + for (const user of usersWithTelegram) { + console.log(`Starting Telegram polling for user ${user.id}`); + await poller.addUser(user); + } + + console.log('Telegram polling initialized successfully'); + } else { + console.log('No users with Telegram configuration found'); + } + } catch (error) { + console.error('Error initializing Telegram polling:', error.message); + console.error('Telegram polling will be initialized later when the database is available.'); + } +} + +module.exports = { initializeTelegramPolling }; \ No newline at end of file diff --git a/backend/services/telegramPoller.js b/backend/services/telegramPoller.js new file mode 100644 index 0000000..2a73050 --- /dev/null +++ b/backend/services/telegramPoller.js @@ -0,0 +1,261 @@ +const https = require('https'); +const { User, InboxItem } = require('../models'); + +class TelegramPoller { + constructor() { + this.running = false; + this.interval = null; + this.pollInterval = 5000; // 5 seconds + this.usersToPool = []; + this.userStatus = {}; + } + + // Singleton pattern + static getInstance() { + if (!TelegramPoller.instance) { + TelegramPoller.instance = new TelegramPoller(); + } + return TelegramPoller.instance; + } + + // Add user to polling list + async addUser(user) { + if (!user || !user.telegram_bot_token) { + return false; + } + + // Check if user already in list + const exists = this.usersToPool.find(u => u.id === user.id); + if (!exists) { + this.usersToPool.push(user); + } + + // Start polling if not already running + if (this.usersToPool.length > 0 && !this.running) { + this.startPolling(); + } + + return true; + } + + // Remove user from polling list + removeUser(userId) { + this.usersToPool = this.usersToPool.filter(u => u.id !== userId); + delete this.userStatus[userId]; + + // Stop polling if no users left + if (this.usersToPool.length === 0 && this.running) { + this.stopPolling(); + } + + return true; + } + + // Start the polling process + startPolling() { + if (this.running) return; + + console.log('Starting Telegram polling...'); + this.running = true; + + this.interval = setInterval(async () => { + try { + await this.pollUpdates(); + } catch (error) { + console.error('Error polling Telegram:', error.message); + } + }, this.pollInterval); + } + + // Stop the polling process + stopPolling() { + if (!this.running) return; + + console.log('Stopping Telegram polling...'); + this.running = false; + + if (this.interval) { + clearInterval(this.interval); + this.interval = null; + } + } + + // Poll for updates from Telegram + async pollUpdates() { + for (const user of this.usersToPool) { + const token = user.telegram_bot_token; + if (!token) continue; + + try { + const lastUpdateId = this.userStatus[user.id]?.lastUpdateId || 0; + const updates = await this.getTelegramUpdates(token, lastUpdateId + 1); + + if (updates && updates.length > 0) { + await this.processUpdates(user, updates); + } + } catch (error) { + console.error(`Error getting updates for user ${user.id}:`, error.message); + } + } + } + + // Get updates from Telegram API + getTelegramUpdates(token, offset) { + return new Promise((resolve, reject) => { + const url = `https://api.telegram.org/bot${token}/getUpdates?offset=${offset}&timeout=1`; + + https.get(url, { timeout: 5000 }, (res) => { + let data = ''; + + res.on('data', (chunk) => { + data += chunk; + }); + + res.on('end', () => { + try { + const response = JSON.parse(data); + if (response.ok && Array.isArray(response.result)) { + resolve(response.result); + } else { + console.error('Telegram API error:', response); + resolve([]); + } + } catch (error) { + reject(error); + } + }); + }).on('error', (error) => { + reject(error); + }).on('timeout', () => { + reject(new Error('Request timeout')); + }); + }); + } + + // Process updates received from Telegram + async processUpdates(user, updates) { + if (!updates.length) return; + + // Track the highest update_id + const highestUpdateId = Math.max(...updates.map(u => u.update_id)); + + // Save the last update ID for this user + if (!this.userStatus[user.id]) { + this.userStatus[user.id] = {}; + } + this.userStatus[user.id].lastUpdateId = highestUpdateId; + + for (const update of updates) { + try { + if (update.message && update.message.text) { + await this.processMessage(user, update); + } + } catch (error) { + console.error(`Error processing update ${update.update_id}:`, error.message); + } + } + } + + // Process a single message + async processMessage(user, update) { + const message = update.message; + const text = message.text; + const chatId = message.chat.id.toString(); + const messageId = message.message_id; + + console.log(`Processing message from user ${user.id}: ${text}`); + + // Save the chat_id if not already saved + if (!user.telegram_chat_id) { + console.log(`Updating user's telegram_chat_id to ${chatId}`); + await User.update( + { telegram_chat_id: chatId }, + { where: { id: user.id } } + ); + user.telegram_chat_id = chatId; // Update local object + } + + try { + // Create an inbox item + const inboxItem = await InboxItem.create({ + content: text, + source: 'telegram', + user_id: user.id + }); + + console.log(`Created inbox item ${inboxItem.id} from Telegram message`); + + // Send confirmation + await this.sendTelegramMessage( + user.telegram_bot_token, + chatId, + `✅ Added to Tududi inbox: "${text}"`, + messageId + ); + } catch (error) { + console.error('Failed to create inbox item:', error.message); + + // Send error message + await this.sendTelegramMessage( + user.telegram_bot_token, + chatId, + `❌ Failed to add to inbox: ${error.message}`, + messageId + ); + } + } + + // Send a message to Telegram + sendTelegramMessage(token, chatId, text, replyToMessageId = null) { + return new Promise((resolve, reject) => { + const messageParams = { + chat_id: chatId, + text: text + }; + + if (replyToMessageId) { + messageParams.reply_to_message_id = replyToMessageId; + } + + const postData = JSON.stringify(messageParams); + const url = `https://api.telegram.org/bot${token}/sendMessage`; + + const options = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Content-Length': Buffer.byteLength(postData) + } + }; + + const req = https.request(url, options, (res) => { + let data = ''; + res.on('data', (chunk) => data += chunk); + res.on('end', () => { + try { + const response = JSON.parse(data); + resolve(response); + } catch (error) { + reject(error); + } + }); + }); + + req.on('error', reject); + req.write(postData); + req.end(); + }); + } + + // Get status of the poller + getStatus() { + return { + running: this.running, + usersCount: this.usersToPool.length, + pollInterval: this.pollInterval, + userStatus: this.userStatus + }; + } +} + +module.exports = TelegramPoller; \ No newline at end of file diff --git a/backend/start.sh b/backend/start.sh new file mode 100755 index 0000000..3fd3f0e --- /dev/null +++ b/backend/start.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# Start script for Express backend + +echo "Starting Express backend..." +echo "Make sure to set environment variables if needed:" +echo " TUDUDI_SESSION_SECRET=your_secret_here" +echo " TUDUDI_USER_EMAIL=your_email@example.com" +echo " TUDUDI_USER_PASSWORD=your_password" +echo "" + +PORT=3001 npm start \ No newline at end of file diff --git a/backend/tests/README.md b/backend/tests/README.md new file mode 100644 index 0000000..e76f1fb --- /dev/null +++ b/backend/tests/README.md @@ -0,0 +1,82 @@ +# Backend Test Suite + +This directory contains the test suite for the tududi backend Express application. + +## Structure + +``` +tests/ +├── unit/ # Unit tests for individual components +│ ├── models/ # Model tests +│ ├── middleware/ # Middleware tests +│ └── services/ # Service tests +├── integration/ # Integration tests for API endpoints +├── fixtures/ # Test data fixtures +└── helpers/ # Test utilities and helpers +``` + +## Running Tests + +### All Tests +```bash +npm test +``` + +### Unit Tests Only +```bash +npm run test:unit +``` + +### Integration Tests Only +```bash +npm run test:integration +``` + +### Watch Mode (for development) +```bash +npm run test:watch +``` + +### Coverage Report +```bash +npm run test:coverage +``` + +## Test Environment + +Tests run in a separate test environment with: +- In-memory SQLite database (isolated from development data) +- Test-specific configuration from `.env.test` +- Automatic database cleanup between tests + +## Writing Tests + +### Unit Tests +- Test individual functions, models, or middleware in isolation +- Mock external dependencies +- Focus on business logic and edge cases + +### Integration Tests +- Test complete API endpoints +- Use authenticated requests where needed +- Test real database interactions +- Verify response formats and status codes + +### Test Utilities +- `tests/helpers/testUtils.js` provides utilities for creating test data +- `tests/helpers/setup.js` handles database setup and cleanup +- Use `createTestUser()` for creating authenticated test users + +## Best Practices + +1. **Isolation**: Each test should be independent and not rely on other tests +2. **Cleanup**: Database is automatically cleaned between tests +3. **Authentication**: Use test utilities for creating authenticated requests +4. **Descriptive Names**: Test names should clearly describe what is being tested +5. **Coverage**: Aim for high test coverage of critical business logic + +## Dependencies + +- **Jest**: Test framework +- **Supertest**: HTTP testing library for integration tests +- **cross-env**: Cross-platform environment variable setting \ No newline at end of file diff --git a/backend/tests/helpers/setup.js b/backend/tests/helpers/setup.js new file mode 100644 index 0000000..651bc9a --- /dev/null +++ b/backend/tests/helpers/setup.js @@ -0,0 +1,39 @@ +// Set test environment before importing models +process.env.NODE_ENV = 'test'; + +const { sequelize } = require('../../models'); + +beforeAll(async () => { + await sequelize.sync({ force: true }); +}, 30000); + +beforeEach(async () => { + // Clean all tables except Sessions to avoid conflicts + try { + const models = Object.values(sequelize.models); + const nonSessionModels = models.filter(model => model.name !== 'Session'); + await Promise.all(nonSessionModels.map(model => model.destroy({ truncate: true, cascade: true }))); + } catch (error) { + // Ignore errors during cleanup + } +}); + +afterEach(async () => { + // Clean up sessions after each test + try { + const Session = sequelize.models.Session; + if (Session) { + await Session.destroy({ truncate: true }); + } + } catch (error) { + // Ignore errors during session cleanup + } +}); + +afterAll(async () => { + try { + await sequelize.close(); + } catch (error) { + // Database may already be closed + } +}, 30000); \ No newline at end of file diff --git a/backend/tests/helpers/testUtils.js b/backend/tests/helpers/testUtils.js new file mode 100644 index 0000000..18d0571 --- /dev/null +++ b/backend/tests/helpers/testUtils.js @@ -0,0 +1,28 @@ +const bcrypt = require('bcrypt'); +const { User } = require('../../models'); + +const createTestUser = async (userData = {}) => { + const defaultUser = { + email: 'test@example.com', + password_digest: await bcrypt.hash('password123', 10), + ...userData + }; + + return await User.create(defaultUser); +}; + +const authenticateUser = async (request, user) => { + const response = await request + .post('/api/login') + .send({ + email: user.email, + password: 'password123' + }); + + return response.headers['set-cookie']; +}; + +module.exports = { + createTestUser, + authenticateUser +}; \ No newline at end of file diff --git a/backend/tests/integration/areas.test.js b/backend/tests/integration/areas.test.js new file mode 100644 index 0000000..99140e5 --- /dev/null +++ b/backend/tests/integration/areas.test.js @@ -0,0 +1,280 @@ +const request = require('supertest'); +const app = require('../../app'); +const { Area, User } = require('../../models'); +const { createTestUser } = require('../helpers/testUtils'); + +describe('Areas Routes', () => { + let user, agent; + + beforeEach(async () => { + user = await createTestUser({ + email: 'test@example.com' + }); + + // Create authenticated agent + agent = request.agent(app); + await agent + .post('/api/login') + .send({ + email: 'test@example.com', + password: 'password123' + }); + }); + + describe('POST /api/areas', () => { + it('should create a new area', async () => { + const areaData = { + name: 'Work', + description: 'Work related projects' + }; + + const response = await agent + .post('/api/areas') + .send(areaData); + + expect(response.status).toBe(201); + expect(response.body.name).toBe(areaData.name); + expect(response.body.description).toBe(areaData.description); + expect(response.body.user_id).toBe(user.id); + }); + + it('should require authentication', async () => { + const areaData = { + name: 'Work' + }; + + const response = await request(app) + .post('/api/areas') + .send(areaData); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + + it('should require area name', async () => { + const areaData = { + description: 'Area without name' + }; + + const response = await agent + .post('/api/areas') + .send(areaData); + + expect(response.status).toBe(400); + expect(response.body.error).toBe('Area name is required.'); + }); + }); + + describe('GET /api/areas', () => { + let area1, area2; + + beforeEach(async () => { + area1 = await Area.create({ + name: 'Work', + description: 'Work projects', + user_id: user.id + }); + + area2 = await Area.create({ + name: 'Personal', + description: 'Personal projects', + user_id: user.id + }); + }); + + it('should get all user areas', async () => { + const response = await agent.get('/api/areas'); + + expect(response.status).toBe(200); + expect(response.body).toHaveLength(2); + expect(response.body.map(a => a.id)).toContain(area1.id); + expect(response.body.map(a => a.id)).toContain(area2.id); + }); + + it('should order areas by name', async () => { + const response = await agent.get('/api/areas'); + + expect(response.status).toBe(200); + expect(response.body[0].name).toBe('Personal'); // P comes before W + expect(response.body[1].name).toBe('Work'); + }); + + it('should require authentication', async () => { + const response = await request(app).get('/api/areas'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('GET /api/areas/:id', () => { + let area; + + beforeEach(async () => { + area = await Area.create({ + name: 'Work', + description: 'Work projects', + user_id: user.id + }); + }); + + it('should get area by id', async () => { + const response = await agent.get(`/api/areas/${area.id}`); + + expect(response.status).toBe(200); + expect(response.body.id).toBe(area.id); + expect(response.body.name).toBe(area.name); + expect(response.body.description).toBe(area.description); + }); + + it('should return 404 for non-existent area', async () => { + const response = await agent.get('/api/areas/999999'); + + expect(response.status).toBe(404); + expect(response.body.error).toBe("Area not found or doesn't belong to the current user."); + }); + + it('should not allow access to other user\'s areas', async () => { + const bcrypt = require('bcrypt'); + const otherUser = await User.create({ + email: 'other@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + const otherArea = await Area.create({ + name: 'Other Area', + user_id: otherUser.id + }); + + const response = await agent.get(`/api/areas/${otherArea.id}`); + + expect(response.status).toBe(404); + expect(response.body.error).toBe("Area not found or doesn't belong to the current user."); + }); + + it('should require authentication', async () => { + const response = await request(app).get(`/api/areas/${area.id}`); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('PATCH /api/areas/:id', () => { + let area; + + beforeEach(async () => { + area = await Area.create({ + name: 'Work', + description: 'Work projects', + user_id: user.id + }); + }); + + it('should update area', async () => { + const updateData = { + name: 'Updated Work', + description: 'Updated description' + }; + + const response = await agent + .patch(`/api/areas/${area.id}`) + .send(updateData); + + expect(response.status).toBe(200); + expect(response.body.name).toBe(updateData.name); + expect(response.body.description).toBe(updateData.description); + }); + + it('should return 404 for non-existent area', async () => { + const response = await agent + .patch('/api/areas/999999') + .send({ name: 'Updated' }); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Area not found.'); + }); + + it('should not allow updating other user\'s areas', async () => { + const bcrypt = require('bcrypt'); + const otherUser = await User.create({ + email: 'other@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + const otherArea = await Area.create({ + name: 'Other Area', + user_id: otherUser.id + }); + + const response = await agent + .patch(`/api/areas/${otherArea.id}`) + .send({ name: 'Updated' }); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Area not found.'); + }); + + it('should require authentication', async () => { + const response = await request(app) + .patch(`/api/areas/${area.id}`) + .send({ name: 'Updated' }); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('DELETE /api/areas/:id', () => { + let area; + + beforeEach(async () => { + area = await Area.create({ + name: 'Work', + user_id: user.id + }); + }); + + it('should delete area', async () => { + const response = await agent.delete(`/api/areas/${area.id}`); + + expect(response.status).toBe(204); + + // Verify area is deleted + const deletedArea = await Area.findByPk(area.id); + expect(deletedArea).toBeNull(); + }); + + it('should return 404 for non-existent area', async () => { + const response = await agent.delete('/api/areas/999999'); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Area not found.'); + }); + + it('should not allow deleting other user\'s areas', async () => { + const bcrypt = require('bcrypt'); + const otherUser = await User.create({ + email: 'other@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + const otherArea = await Area.create({ + name: 'Other Area', + user_id: otherUser.id + }); + + const response = await agent.delete(`/api/areas/${otherArea.id}`); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Area not found.'); + }); + + it('should require authentication', async () => { + const response = await request(app).delete(`/api/areas/${area.id}`); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/integration/auth.test.js b/backend/tests/integration/auth.test.js new file mode 100644 index 0000000..81e61f9 --- /dev/null +++ b/backend/tests/integration/auth.test.js @@ -0,0 +1,155 @@ +const request = require('supertest'); +const app = require('../../app'); +const { User } = require('../../models'); +const { createTestUser } = require('../helpers/testUtils'); + +describe('Auth Routes', () => { + describe('POST /api/login', () => { + let user; + + beforeEach(async () => { + user = await createTestUser({ + email: 'test@example.com' + }); + }); + + it('should login with valid credentials', async () => { + const response = await request(app) + .post('/api/login') + .send({ + email: 'test@example.com', + password: 'password123' + }); + + expect(response.status).toBe(200); + expect(response.body.user).toBeDefined(); + expect(response.body.user.email).toBe('test@example.com'); + expect(response.body.user.id).toBe(user.id); + expect(response.body.user.language).toBe('en'); + expect(response.body.user.appearance).toBe('light'); + expect(response.body.user.timezone).toBe('UTC'); + }); + + it('should return 400 for missing email', async () => { + const response = await request(app) + .post('/api/login') + .send({ + password: 'password123' + }); + + expect(response.status).toBe(400); + expect(response.body.error).toBe('Invalid login parameters.'); + }); + + it('should return 400 for missing password', async () => { + const response = await request(app) + .post('/api/login') + .send({ + email: 'test@example.com' + }); + + expect(response.status).toBe(400); + expect(response.body.error).toBe('Invalid login parameters.'); + }); + + it('should return 401 for non-existent user', async () => { + const response = await request(app) + .post('/api/login') + .send({ + email: 'nonexistent@example.com', + password: 'password123' + }); + + expect(response.status).toBe(401); + expect(response.body.errors).toEqual(['Invalid credentials']); + }); + + it('should return 401 for invalid password', async () => { + const response = await request(app) + .post('/api/login') + .send({ + email: 'test@example.com', + password: 'wrongpassword' + }); + + expect(response.status).toBe(401); + expect(response.body.errors).toEqual(['Invalid credentials']); + }); + }); + + describe('GET /api/current_user', () => { + let user; + + beforeEach(async () => { + user = await createTestUser({ + email: 'test@example.com' + }); + }); + + it('should return current user when logged in', async () => { + const agent = request.agent(app); + + // Login first + await agent + .post('/api/login') + .send({ + email: 'test@example.com', + password: 'password123' + }); + + // Check current user + const response = await agent.get('/api/current_user'); + + expect(response.status).toBe(200); + expect(response.body.user).toBeDefined(); + expect(response.body.user.email).toBe('test@example.com'); + expect(response.body.user.id).toBe(user.id); + }); + + it('should return null user when not logged in', async () => { + const response = await request(app).get('/api/current_user'); + + expect(response.status).toBe(200); + expect(response.body.user).toBeNull(); + }); + }); + + describe('GET /api/logout', () => { + let user; + + beforeEach(async () => { + user = await createTestUser({ + email: 'test@example.com' + }); + }); + + it('should logout successfully', async () => { + const agent = request.agent(app); + + // Login first + await agent + .post('/api/login') + .send({ + email: 'test@example.com', + password: 'password123' + }); + + // Logout + const response = await agent.get('/api/logout'); + + expect(response.status).toBe(200); + expect(response.body.message).toBe('Logged out successfully'); + + // Verify user is logged out + const currentUserResponse = await agent.get('/api/current_user'); + expect(currentUserResponse.body.user).toBeNull(); + }); + + it('should handle logout when not logged in', async () => { + const response = await request(app).get('/api/logout'); + + expect(response.status).toBe(200); + expect(response.body.message).toBe('Logged out successfully'); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/integration/inbox.test.js b/backend/tests/integration/inbox.test.js new file mode 100644 index 0000000..cc7d6b5 --- /dev/null +++ b/backend/tests/integration/inbox.test.js @@ -0,0 +1,275 @@ +const request = require('supertest'); +const app = require('../../app'); +const { InboxItem, User } = require('../../models'); +const { createTestUser } = require('../helpers/testUtils'); + +describe('Inbox Routes', () => { + let user, agent; + + beforeEach(async () => { + user = await createTestUser({ + email: 'test@example.com' + }); + + // Create authenticated agent + agent = request.agent(app); + await agent + .post('/api/login') + .send({ + email: 'test@example.com', + password: 'password123' + }); + }); + + describe('POST /api/inbox', () => { + it('should create a new inbox item', async () => { + const inboxData = { + content: 'Remember to buy groceries', + source: 'web' + }; + + const response = await agent + .post('/api/inbox') + .send(inboxData); + + expect(response.status).toBe(201); + expect(response.body.content).toBe(inboxData.content); + expect(response.body.source).toBe(inboxData.source); + expect(response.body.status).toBe('added'); + expect(response.body.user_id).toBe(user.id); + }); + + it('should require authentication', async () => { + const inboxData = { + content: 'Test content' + }; + + const response = await request(app) + .post('/api/inbox') + .send(inboxData); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + + it('should require content', async () => { + const inboxData = {}; + + const response = await agent + .post('/api/inbox') + .send(inboxData); + + expect(response.status).toBe(400); + expect(response.body.error).toBe('Content is required'); + }); + }); + + describe('GET /api/inbox', () => { + let inboxItem1, inboxItem2; + + beforeEach(async () => { + inboxItem1 = await InboxItem.create({ + content: 'First item', + status: 'added', + user_id: user.id + }); + + inboxItem2 = await InboxItem.create({ + content: 'Second item', + status: 'processed', + user_id: user.id + }); + }); + + it('should get all user inbox items', async () => { + const response = await agent.get('/api/inbox'); + + expect(response.status).toBe(200); + expect(Array.isArray(response.body)).toBe(true); + expect(response.body.length).toBe(1); // Only items with status 'added' are returned + expect(response.body.map(i => i.id)).toContain(inboxItem1.id); + }); + + it('should only return items with added status', async () => { + const response = await agent.get('/api/inbox'); + + expect(response.status).toBe(200); + expect(response.body.length).toBe(1); + expect(response.body[0].id).toBe(inboxItem1.id); + expect(response.body[0].status).toBe('added'); + }); + + it('should require authentication', async () => { + const response = await request(app).get('/api/inbox'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('GET /api/inbox/:id', () => { + let inboxItem; + + beforeEach(async () => { + inboxItem = await InboxItem.create({ + content: 'Test content', + user_id: user.id + }); + }); + + it('should get inbox item by id', async () => { + const response = await agent.get(`/api/inbox/${inboxItem.id}`); + + expect(response.status).toBe(200); + expect(response.body.id).toBe(inboxItem.id); + expect(response.body.content).toBe(inboxItem.content); + }); + + it('should return 404 for non-existent inbox item', async () => { + const response = await agent.get('/api/inbox/999999'); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Inbox item not found.'); + }); + + it('should not allow access to other user\'s inbox items', async () => { + const bcrypt = require('bcrypt'); + const otherUser = await User.create({ + email: 'other@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + const otherInboxItem = await InboxItem.create({ + content: 'Other content', + user_id: otherUser.id + }); + + const response = await agent.get(`/api/inbox/${otherInboxItem.id}`); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Inbox item not found.'); + }); + + it('should require authentication', async () => { + const response = await request(app).get(`/api/inbox/${inboxItem.id}`); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('PATCH /api/inbox/:id', () => { + let inboxItem; + + beforeEach(async () => { + inboxItem = await InboxItem.create({ + content: 'Test content', + status: 'added', + user_id: user.id + }); + }); + + it('should update inbox item', async () => { + const updateData = { + content: 'Updated content', + status: 'processed' + }; + + const response = await agent + .patch(`/api/inbox/${inboxItem.id}`) + .send(updateData); + + expect(response.status).toBe(200); + expect(response.body.content).toBe(updateData.content); + expect(response.body.status).toBe(updateData.status); + }); + + it('should return 404 for non-existent inbox item', async () => { + const response = await agent + .patch('/api/inbox/999999') + .send({ content: 'Updated' }); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Inbox item not found.'); + }); + + it('should require authentication', async () => { + const response = await request(app) + .patch(`/api/inbox/${inboxItem.id}`) + .send({ content: 'Updated' }); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('DELETE /api/inbox/:id', () => { + let inboxItem; + + beforeEach(async () => { + inboxItem = await InboxItem.create({ + content: 'Test content', + user_id: user.id + }); + }); + + it('should delete inbox item', async () => { + const response = await agent.delete(`/api/inbox/${inboxItem.id}`); + + expect(response.status).toBe(200); + expect(response.body.message).toBe('Inbox item successfully deleted'); + + // Verify inbox item status is updated to deleted + const deletedItem = await InboxItem.findByPk(inboxItem.id); + expect(deletedItem).not.toBeNull(); + expect(deletedItem.status).toBe('deleted'); + }); + + it('should return 404 for non-existent inbox item', async () => { + const response = await agent.delete('/api/inbox/999999'); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Inbox item not found.'); + }); + + it('should require authentication', async () => { + const response = await request(app).delete(`/api/inbox/${inboxItem.id}`); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('PATCH /api/inbox/:id/process', () => { + let inboxItem; + + beforeEach(async () => { + inboxItem = await InboxItem.create({ + content: 'Test content', + status: 'added', + user_id: user.id + }); + }); + + it('should process inbox item', async () => { + const response = await agent.patch(`/api/inbox/${inboxItem.id}/process`); + + expect(response.status).toBe(200); + expect(response.body.status).toBe('processed'); + }); + + it('should return 404 for non-existent inbox item', async () => { + const response = await agent.patch('/api/inbox/999999/process'); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Inbox item not found.'); + }); + + it('should require authentication', async () => { + const response = await request(app).patch(`/api/inbox/${inboxItem.id}/process`); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/integration/notes.test.js b/backend/tests/integration/notes.test.js new file mode 100644 index 0000000..7ac001b --- /dev/null +++ b/backend/tests/integration/notes.test.js @@ -0,0 +1,308 @@ +const request = require('supertest'); +const app = require('../../app'); +const { Note, User, Project } = require('../../models'); +const { createTestUser } = require('../helpers/testUtils'); + +describe('Notes Routes', () => { + let user, project, agent; + + beforeEach(async () => { + user = await createTestUser({ + email: 'test@example.com' + }); + + project = await Project.create({ + name: 'Test Project', + user_id: user.id + }); + + // Create authenticated agent + agent = request.agent(app); + await agent + .post('/api/login') + .send({ + email: 'test@example.com', + password: 'password123' + }); + }); + + describe('POST /api/note', () => { + it('should create a new note', async () => { + const noteData = { + title: 'Test Note', + content: 'This is a test note content', + project_id: project.id + }; + + const response = await agent + .post('/api/note') + .send(noteData); + + expect(response.status).toBe(201); + expect(response.body.title).toBe(noteData.title); + expect(response.body.content).toBe(noteData.content); + expect(response.body.project_id).toBe(project.id); + expect(response.body.user_id).toBe(user.id); + }); + + it('should create note without project', async () => { + const noteData = { + title: 'Test Note', + content: 'This is a test note content' + }; + + const response = await agent + .post('/api/note') + .send(noteData); + + expect(response.status).toBe(201); + expect(response.body.title).toBe(noteData.title); + expect(response.body.content).toBe(noteData.content); + expect(response.body.project_id).toBeNull(); + expect(response.body.user_id).toBe(user.id); + }); + + it('should require authentication', async () => { + const noteData = { + title: 'Test Note', + content: 'Test content' + }; + + const response = await request(app) + .post('/api/note') + .send(noteData); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('GET /api/notes', () => { + let note1, note2; + + beforeEach(async () => { + note1 = await Note.create({ + title: 'Note 1', + content: 'First note content', + user_id: user.id, + project_id: project.id + }); + + note2 = await Note.create({ + title: 'Note 2', + content: 'Second note content', + user_id: user.id + }); + }); + + it('should get all user notes', async () => { + const response = await agent.get('/api/notes'); + + expect(response.status).toBe(200); + expect(Array.isArray(response.body)).toBe(true); + expect(response.body.length).toBe(2); + expect(response.body.map(n => n.id)).toContain(note1.id); + expect(response.body.map(n => n.id)).toContain(note2.id); + }); + + it('should include project information', async () => { + const response = await agent.get('/api/notes'); + + expect(response.status).toBe(200); + const noteWithProject = response.body.find(n => n.id === note1.id); + expect(noteWithProject.Project).toBeDefined(); + expect(noteWithProject.Project.name).toBe(project.name); + }); + + it('should return all notes when no filter is applied', async () => { + const response = await agent.get('/api/notes'); + + expect(response.status).toBe(200); + expect(response.body.length).toBe(2); + expect(response.body.map(n => n.id)).toContain(note1.id); + expect(response.body.map(n => n.id)).toContain(note2.id); + }); + + it('should require authentication', async () => { + const response = await request(app).get('/api/notes'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('GET /api/note/:id', () => { + let note; + + beforeEach(async () => { + note = await Note.create({ + title: 'Test Note', + content: 'Test content', + user_id: user.id, + project_id: project.id + }); + }); + + it('should get note by id', async () => { + const response = await agent.get(`/api/note/${note.id}`); + + expect(response.status).toBe(200); + expect(response.body.id).toBe(note.id); + expect(response.body.title).toBe(note.title); + expect(response.body.content).toBe(note.content); + }); + + it('should return 404 for non-existent note', async () => { + const response = await agent.get('/api/note/999999'); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Note not found.'); + }); + + it('should not allow access to other user\'s notes', async () => { + const bcrypt = require('bcrypt'); + const otherUser = await User.create({ + email: 'other@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + const otherNote = await Note.create({ + title: 'Other Note', + user_id: otherUser.id + }); + + const response = await agent.get(`/api/note/${otherNote.id}`); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Note not found.'); + }); + + it('should require authentication', async () => { + const response = await request(app).get(`/api/note/${note.id}`); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('PATCH /api/note/:id', () => { + let note; + + beforeEach(async () => { + note = await Note.create({ + title: 'Test Note', + content: 'Test content', + user_id: user.id + }); + }); + + it('should update note', async () => { + const updateData = { + title: 'Updated Note', + content: 'Updated content', + project_id: project.id + }; + + const response = await agent + .patch(`/api/note/${note.id}`) + .send(updateData); + + expect(response.status).toBe(200); + expect(response.body.title).toBe(updateData.title); + expect(response.body.content).toBe(updateData.content); + expect(response.body.project_id).toBe(project.id); + }); + + it('should return 404 for non-existent note', async () => { + const response = await agent + .patch('/api/note/999999') + .send({ title: 'Updated' }); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Note not found.'); + }); + + it('should not allow updating other user\'s notes', async () => { + const bcrypt = require('bcrypt'); + const otherUser = await User.create({ + email: 'other@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + const otherNote = await Note.create({ + title: 'Other Note', + user_id: otherUser.id + }); + + const response = await agent + .patch(`/api/note/${otherNote.id}`) + .send({ title: 'Updated' }); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Note not found.'); + }); + + it('should require authentication', async () => { + const response = await request(app) + .patch(`/api/note/${note.id}`) + .send({ title: 'Updated' }); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('DELETE /api/note/:id', () => { + let note; + + beforeEach(async () => { + note = await Note.create({ + title: 'Test Note', + user_id: user.id + }); + }); + + it('should delete note', async () => { + const response = await agent.delete(`/api/note/${note.id}`); + + expect(response.status).toBe(200); + expect(response.body.message).toBe('Note deleted successfully.'); + + // Verify note is deleted + const deletedNote = await Note.findByPk(note.id); + expect(deletedNote).toBeNull(); + }); + + it('should return 404 for non-existent note', async () => { + const response = await agent.delete('/api/note/999999'); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Note not found.'); + }); + + it('should not allow deleting other user\'s notes', async () => { + const bcrypt = require('bcrypt'); + const otherUser = await User.create({ + email: 'other@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + const otherNote = await Note.create({ + title: 'Other Note', + user_id: otherUser.id + }); + + const response = await agent.delete(`/api/note/${otherNote.id}`); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Note not found.'); + }); + + it('should require authentication', async () => { + const response = await request(app).delete(`/api/note/${note.id}`); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/integration/projects.test.js b/backend/tests/integration/projects.test.js new file mode 100644 index 0000000..016064a --- /dev/null +++ b/backend/tests/integration/projects.test.js @@ -0,0 +1,303 @@ +const request = require('supertest'); +const app = require('../../app'); +const { Project, User, Area } = require('../../models'); +const { createTestUser } = require('../helpers/testUtils'); + +describe('Projects Routes', () => { + let user, area, agent; + + beforeEach(async () => { + user = await createTestUser({ + email: 'test@example.com' + }); + + area = await Area.create({ + name: 'Work', + user_id: user.id + }); + + // Create authenticated agent + agent = request.agent(app); + await agent + .post('/api/login') + .send({ + email: 'test@example.com', + password: 'password123' + }); + }); + + describe('POST /api/project', () => { + it('should create a new project', async () => { + const projectData = { + name: 'Test Project', + description: 'Test Description', + active: true, + pin_to_sidebar: false, + priority: 1, + area_id: area.id + }; + + const response = await agent + .post('/api/project') + .send(projectData); + + expect(response.status).toBe(201); + expect(response.body.name).toBe(projectData.name); + expect(response.body.description).toBe(projectData.description); + expect(response.body.active).toBe(projectData.active); + expect(response.body.pin_to_sidebar).toBe(projectData.pin_to_sidebar); + expect(response.body.priority).toBe(projectData.priority); + expect(response.body.area_id).toBe(area.id); + expect(response.body.user_id).toBe(user.id); + }); + + it('should require authentication', async () => { + const projectData = { + name: 'Test Project' + }; + + const response = await request(app) + .post('/api/project') + .send(projectData); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + + it('should require project name', async () => { + const projectData = { + description: 'Project without name' + }; + + const response = await agent + .post('/api/project') + .send(projectData); + + expect(response.status).toBe(400); + }); + }); + + describe('GET /api/projects', () => { + let project1, project2; + + beforeEach(async () => { + project1 = await Project.create({ + name: 'Project 1', + description: 'First project', + user_id: user.id, + area_id: area.id + }); + + project2 = await Project.create({ + name: 'Project 2', + description: 'Second project', + user_id: user.id + }); + }); + + it('should get all user projects', async () => { + const response = await agent.get('/api/projects'); + + expect(response.status).toBe(200); + expect(response.body.projects).toBeDefined(); + expect(response.body.projects.length).toBe(2); + expect(response.body.projects.map(p => p.id)).toContain(project1.id); + expect(response.body.projects.map(p => p.id)).toContain(project2.id); + }); + + it('should include area information', async () => { + const response = await agent.get('/api/projects'); + + expect(response.status).toBe(200); + const projectWithArea = response.body.projects.find(p => p.id === project1.id); + expect(projectWithArea.Area).toBeDefined(); + expect(projectWithArea.Area.name).toBe(area.name); + }); + + it('should require authentication', async () => { + const response = await request(app).get('/api/projects'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('GET /api/project/:id', () => { + let project; + + beforeEach(async () => { + project = await Project.create({ + name: 'Test Project', + description: 'Test Description', + user_id: user.id, + area_id: area.id + }); + }); + + it('should get project by id', async () => { + const response = await agent.get(`/api/project/${project.id}`); + + expect(response.status).toBe(200); + expect(response.body.id).toBe(project.id); + expect(response.body.name).toBe(project.name); + expect(response.body.description).toBe(project.description); + }); + + it('should return 404 for non-existent project', async () => { + const response = await agent.get('/api/project/999999'); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Project not found'); + }); + + it('should not allow access to other user\'s projects', async () => { + const bcrypt = require('bcrypt'); + const otherUser = await User.create({ + email: 'other@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + const otherProject = await Project.create({ + name: 'Other Project', + user_id: otherUser.id + }); + + const response = await agent.get(`/api/project/${otherProject.id}`); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Project not found'); + }); + + it('should require authentication', async () => { + const response = await request(app).get(`/api/project/${project.id}`); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('PATCH /api/project/:id', () => { + let project; + + beforeEach(async () => { + project = await Project.create({ + name: 'Test Project', + description: 'Test Description', + active: false, + priority: 0, + user_id: user.id + }); + }); + + it('should update project', async () => { + const updateData = { + name: 'Updated Project', + description: 'Updated Description', + active: true, + priority: 2 + }; + + const response = await agent + .patch(`/api/project/${project.id}`) + .send(updateData); + + expect(response.status).toBe(200); + expect(response.body.name).toBe(updateData.name); + expect(response.body.description).toBe(updateData.description); + expect(response.body.active).toBe(updateData.active); + expect(response.body.priority).toBe(updateData.priority); + }); + + it('should return 404 for non-existent project', async () => { + const response = await agent + .patch('/api/project/999999') + .send({ name: 'Updated' }); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Project not found.'); + }); + + it('should not allow updating other user\'s projects', async () => { + const bcrypt = require('bcrypt'); + const otherUser = await User.create({ + email: 'other@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + const otherProject = await Project.create({ + name: 'Other Project', + user_id: otherUser.id + }); + + const response = await agent + .patch(`/api/project/${otherProject.id}`) + .send({ name: 'Updated' }); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Project not found.'); + }); + + it('should require authentication', async () => { + const response = await request(app) + .patch(`/api/project/${project.id}`) + .send({ name: 'Updated' }); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('DELETE /api/project/:id', () => { + let project; + + beforeEach(async () => { + project = await Project.create({ + name: 'Test Project', + user_id: user.id + }); + }); + + it('should delete project', async () => { + const response = await agent.delete(`/api/project/${project.id}`); + + expect(response.status).toBe(200); + expect(response.body.message).toBe('Project successfully deleted'); + + // Verify project is deleted + const deletedProject = await Project.findByPk(project.id); + expect(deletedProject).toBeNull(); + }); + + it('should return 404 for non-existent project', async () => { + const response = await agent.delete('/api/project/999999'); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Project not found.'); + }); + + it('should not allow deleting other user\'s projects', async () => { + const bcrypt = require('bcrypt'); + const otherUser = await User.create({ + email: 'other@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + const otherProject = await Project.create({ + name: 'Other Project', + user_id: otherUser.id + }); + + const response = await agent.delete(`/api/project/${otherProject.id}`); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Project not found.'); + }); + + it('should require authentication', async () => { + const response = await request(app).delete(`/api/project/${project.id}`); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/integration/quotes.test.js b/backend/tests/integration/quotes.test.js new file mode 100644 index 0000000..57b671b --- /dev/null +++ b/backend/tests/integration/quotes.test.js @@ -0,0 +1,168 @@ +const request = require('supertest'); +const app = require('../../app'); +const { createTestUser } = require('../helpers/testUtils'); + +describe('Quotes Routes', () => { + let user, agent; + + beforeEach(async () => { + user = await createTestUser({ + email: 'test@example.com' + }); + + // Create authenticated agent + agent = request.agent(app); + await agent + .post('/api/login') + .send({ + email: 'test@example.com', + password: 'password123' + }); + }); + + describe('GET /api/quotes/random', () => { + it('should return a random quote', async () => { + const response = await agent + .get('/api/quotes/random'); + + expect(response.status).toBe(200); + expect(response.body).toHaveProperty('quote'); + expect(typeof response.body.quote).toBe('string'); + expect(response.body.quote.length).toBeGreaterThan(0); + }); + + it('should return different quotes on multiple requests', async () => { + const responses = await Promise.all([ + agent.get('/api/quotes/random'), + agent.get('/api/quotes/random'), + agent.get('/api/quotes/random'), + agent.get('/api/quotes/random'), + agent.get('/api/quotes/random') + ]); + + // All responses should be successful + responses.forEach(response => { + expect(response.status).toBe(200); + expect(response.body).toHaveProperty('quote'); + expect(typeof response.body.quote).toBe('string'); + }); + + // With multiple requests, we should get at least some variety + // (though it's possible to get the same quote multiple times due to randomness) + const quotes = responses.map(r => r.body.quote); + const uniqueQuotes = new Set(quotes); + + // We expect at least 1 unique quote, but likely more + expect(uniqueQuotes.size).toBeGreaterThanOrEqual(1); + }); + + it('should return valid quote structure', async () => { + const response = await agent + .get('/api/quotes/random'); + + expect(response.status).toBe(200); + expect(Object.keys(response.body)).toEqual(['quote']); + expect(response.body.quote).toBeTruthy(); + expect(response.body.quote.trim()).toBe(response.body.quote); + }); + }); + + describe('GET /api/quotes', () => { + it('should return all quotes with count', async () => { + const response = await agent + .get('/api/quotes'); + + expect(response.status).toBe(200); + expect(response.body).toHaveProperty('quotes'); + expect(response.body).toHaveProperty('count'); + expect(Array.isArray(response.body.quotes)).toBe(true); + expect(typeof response.body.count).toBe('number'); + expect(response.body.quotes.length).toBe(response.body.count); + expect(response.body.count).toBeGreaterThan(0); + }); + + it('should return valid quote array', async () => { + const response = await agent + .get('/api/quotes'); + + expect(response.status).toBe(200); + + // All quotes should be non-empty strings + response.body.quotes.forEach(quote => { + expect(typeof quote).toBe('string'); + expect(quote.length).toBeGreaterThan(0); + expect(quote.trim()).toBe(quote); + }); + }); + + it('should return consistent data across requests', async () => { + const response1 = await agent.get('/api/quotes'); + const response2 = await agent.get('/api/quotes'); + + expect(response1.status).toBe(200); + expect(response2.status).toBe(200); + + // The quotes array should be the same across requests + expect(response1.body.quotes.length).toBe(response2.body.quotes.length); + expect(response1.body.count).toBe(response2.body.count); + + // Verify the actual content is the same + expect(response1.body.quotes).toEqual(response2.body.quotes); + }); + + it('should return expected quote count', async () => { + const response = await agent + .get('/api/quotes'); + + expect(response.status).toBe(200); + + // Based on the configuration, we expect 20 quotes, but allow for fallback quotes + expect(response.body.count).toBeGreaterThanOrEqual(5); + expect(response.body.quotes.length).toBe(response.body.count); + }); + + it('should contain productivity-focused quotes', async () => { + const response = await agent + .get('/api/quotes'); + + expect(response.status).toBe(200); + + // Look for some productivity-related keywords in the quotes + const allQuotesText = response.body.quotes.join(' ').toLowerCase(); + + // These are common themes in productivity quotes + const productivityKeywords = [ + 'progress', 'task', 'goal', 'focus', 'accomplish', + 'success', 'work', 'effort', 'achieve', 'time' + ]; + + // At least some quotes should contain productivity-related terms + const hasProductivityContent = productivityKeywords.some(keyword => + allQuotesText.includes(keyword) + ); + + expect(hasProductivityContent).toBe(true); + }); + }); + + describe('Quote randomness and consistency', () => { + it('should have random quotes that are part of the full quote set', async () => { + // Get all quotes first + const allQuotesResponse = await agent.get('/api/quotes'); + const allQuotes = allQuotesResponse.body.quotes; + + // Get several random quotes + const randomQuoteResponses = await Promise.all([ + agent.get('/api/quotes/random'), + agent.get('/api/quotes/random'), + agent.get('/api/quotes/random') + ]); + + // Each random quote should be from the full set + randomQuoteResponses.forEach(response => { + expect(response.status).toBe(200); + expect(allQuotes).toContain(response.body.quote); + }); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/integration/tags.test.js b/backend/tests/integration/tags.test.js new file mode 100644 index 0000000..be6e4e5 --- /dev/null +++ b/backend/tests/integration/tags.test.js @@ -0,0 +1,270 @@ +const request = require('supertest'); +const app = require('../../app'); +const { Tag, User } = require('../../models'); +const { createTestUser } = require('../helpers/testUtils'); + +describe('Tags Routes', () => { + let user, agent; + + beforeEach(async () => { + user = await createTestUser({ + email: 'test@example.com' + }); + + // Create authenticated agent + agent = request.agent(app); + await agent + .post('/api/login') + .send({ + email: 'test@example.com', + password: 'password123' + }); + }); + + describe('POST /api/tag', () => { + it('should create a new tag', async () => { + const tagData = { + name: 'work' + }; + + const response = await agent + .post('/api/tag') + .send(tagData); + + expect(response.status).toBe(201); + expect(response.body.name).toBe(tagData.name); + expect(response.body.id).toBeDefined(); + }); + + it('should require authentication', async () => { + const tagData = { + name: 'work' + }; + + const response = await request(app) + .post('/api/tag') + .send(tagData); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + + it('should require tag name', async () => { + const tagData = {}; + + const response = await agent + .post('/api/tag') + .send(tagData); + + expect(response.status).toBe(400); + expect(response.body.error).toBe('Tag name is required'); + }); + }); + + describe('GET /api/tags', () => { + let tag1, tag2; + + beforeEach(async () => { + tag1 = await Tag.create({ + name: 'work', + user_id: user.id + }); + + tag2 = await Tag.create({ + name: 'personal', + user_id: user.id + }); + }); + + it('should get all user tags', async () => { + const response = await agent.get('/api/tags'); + + expect(response.status).toBe(200); + expect(response.body).toHaveLength(2); + expect(response.body.map(t => t.id)).toContain(tag1.id); + expect(response.body.map(t => t.id)).toContain(tag2.id); + }); + + it('should order tags by name', async () => { + const response = await agent.get('/api/tags'); + + expect(response.status).toBe(200); + expect(response.body[0].name).toBe('personal'); // P comes before W + expect(response.body[1].name).toBe('work'); + }); + + it('should require authentication', async () => { + const response = await request(app).get('/api/tags'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('GET /api/tag/:id', () => { + let tag; + + beforeEach(async () => { + tag = await Tag.create({ + name: 'work', + user_id: user.id + }); + }); + + it('should get tag by id', async () => { + const response = await agent.get(`/api/tag/${tag.id}`); + + expect(response.status).toBe(200); + expect(response.body.id).toBe(tag.id); + expect(response.body.name).toBe(tag.name); + }); + + it('should return 404 for non-existent tag', async () => { + const response = await agent.get('/api/tag/999999'); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Tag not found'); + }); + + it('should not allow access to other user\'s tags', async () => { + const bcrypt = require('bcrypt'); + const otherUser = await User.create({ + email: 'other@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + const otherTag = await Tag.create({ + name: 'other-tag', + user_id: otherUser.id + }); + + const response = await agent.get(`/api/tag/${otherTag.id}`); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Tag not found'); + }); + + it('should require authentication', async () => { + const response = await request(app).get(`/api/tag/${tag.id}`); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('PATCH /api/tag/:id', () => { + let tag; + + beforeEach(async () => { + tag = await Tag.create({ + name: 'work', + user_id: user.id + }); + }); + + it('should update tag', async () => { + const updateData = { + name: 'updated-work' + }; + + const response = await agent + .patch(`/api/tag/${tag.id}`) + .send(updateData); + + expect(response.status).toBe(200); + expect(response.body.name).toBe(updateData.name); + }); + + it('should return 404 for non-existent tag', async () => { + const response = await agent + .patch('/api/tag/999999') + .send({ name: 'Updated' }); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Tag not found'); + }); + + it('should not allow updating other user\'s tags', async () => { + const bcrypt = require('bcrypt'); + const otherUser = await User.create({ + email: 'other@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + const otherTag = await Tag.create({ + name: 'other-tag', + user_id: otherUser.id + }); + + const response = await agent + .patch(`/api/tag/${otherTag.id}`) + .send({ name: 'Updated' }); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Tag not found'); + }); + + it('should require authentication', async () => { + const response = await request(app) + .patch(`/api/tag/${tag.id}`) + .send({ name: 'Updated' }); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('DELETE /api/tag/:id', () => { + let tag; + + beforeEach(async () => { + tag = await Tag.create({ + name: 'work', + user_id: user.id + }); + }); + + it('should delete tag', async () => { + const response = await agent.delete(`/api/tag/${tag.id}`); + + expect(response.status).toBe(200); + expect(response.body.message).toBe('Tag successfully deleted'); + + // Verify tag is deleted + const deletedTag = await Tag.findByPk(tag.id); + expect(deletedTag).toBeNull(); + }); + + it('should return 404 for non-existent tag', async () => { + const response = await agent.delete('/api/tag/999999'); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Tag not found'); + }); + + it('should not allow deleting other user\'s tags', async () => { + const bcrypt = require('bcrypt'); + const otherUser = await User.create({ + email: 'other@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + const otherTag = await Tag.create({ + name: 'other-tag', + user_id: otherUser.id + }); + + const response = await agent.delete(`/api/tag/${otherTag.id}`); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Tag not found'); + }); + + it('should require authentication', async () => { + const response = await request(app).delete(`/api/tag/${tag.id}`); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/integration/tasks.test.js b/backend/tests/integration/tasks.test.js new file mode 100644 index 0000000..c6026c0 --- /dev/null +++ b/backend/tests/integration/tasks.test.js @@ -0,0 +1,274 @@ +const request = require('supertest'); +const app = require('../../app'); +const { Task, User } = require('../../models'); +const { createTestUser } = require('../helpers/testUtils'); + +describe('Tasks Routes', () => { + let user, agent; + + beforeEach(async () => { + user = await createTestUser({ + email: 'test@example.com' + }); + + // Create authenticated agent + agent = request.agent(app); + await agent + .post('/api/login') + .send({ + email: 'test@example.com', + password: 'password123' + }); + }); + + describe('POST /api/task', () => { + it('should create a new task', async () => { + const taskData = { + name: 'Test Task', + note: 'Test Note', + priority: 1, + status: 0 + }; + + const response = await agent + .post('/api/task') + .send(taskData); + + expect(response.status).toBe(201); + expect(response.body.id).toBeDefined(); + expect(response.body.name).toBe(taskData.name); + expect(response.body.note).toBe(taskData.note); + expect(response.body.priority).toBe(taskData.priority); + expect(response.body.status).toBe(taskData.status); + expect(response.body.user_id).toBe(user.id); + }); + + it('should require authentication', async () => { + const taskData = { + name: 'Test Task' + }; + + const response = await request(app) + .post('/api/task') + .send(taskData); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + + it('should require task name', async () => { + // Mock console.error to suppress expected error log in test output + const originalConsoleError = console.error; + console.error = jest.fn(); + + const taskData = { + description: 'Test Description' + }; + + const response = await agent + .post('/api/task') + .send(taskData); + + expect(response.status).toBe(400); + + // Restore original console.error + console.error = originalConsoleError; + }); + }); + + describe('GET /api/tasks', () => { + let task1, task2; + + beforeEach(async () => { + task1 = await Task.create({ + name: 'Task 1', + description: 'Description 1', + user_id: user.id, + today: true + }); + + task2 = await Task.create({ + name: 'Task 2', + description: 'Description 2', + user_id: user.id, + today: false + }); + }); + + it('should get all user tasks', async () => { + const response = await agent.get('/api/tasks'); + + expect(response.status).toBe(200); + expect(response.body.tasks).toBeDefined(); + expect(response.body.tasks.length).toBe(2); + expect(response.body.tasks.map(t => t.id)).toContain(task1.id); + expect(response.body.tasks.map(t => t.id)).toContain(task2.id); + }); + + it('should filter today tasks (returns all user tasks)', async () => { + const response = await agent.get('/api/tasks?type=today'); + + expect(response.status).toBe(200); + expect(response.body.tasks).toBeDefined(); + expect(response.body.tasks.length).toBe(2); + // Both tasks should be returned as "today" doesn't filter by the today field + }); + + it('should require authentication', async () => { + const response = await request(app).get('/api/tasks'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + // Note: No individual task GET route exists in the current API + + describe('PATCH /api/task/:id', () => { + let task; + + beforeEach(async () => { + task = await Task.create({ + name: 'Test Task', + description: 'Test Description', + priority: 0, + status: 0, + user_id: user.id + }); + }); + + it('should update task', async () => { + const updateData = { + name: 'Updated Task', + note: 'Updated Note', + priority: 2, + status: 1 + }; + + const response = await agent + .patch(`/api/task/${task.id}`) + .send(updateData); + + expect(response.status).toBe(200); + expect(response.body.id).toBeDefined(); + expect(response.body.name).toBe(updateData.name); + expect(response.body.note).toBe(updateData.note); + expect(response.body.priority).toBe(updateData.priority); + expect(response.body.status).toBe(updateData.status); + }); + + it('should return 404 for non-existent task', async () => { + const response = await agent + .patch('/api/task/999999') + .send({ name: 'Updated' }); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Task not found.'); + }); + + it('should not allow updating other user\'s tasks', async () => { + const bcrypt = require('bcrypt'); + const otherUser = await User.create({ + email: 'other@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + const otherTask = await Task.create({ + name: 'Other Task', + user_id: otherUser.id + }); + + const response = await agent + .patch(`/api/task/${otherTask.id}`) + .send({ name: 'Updated' }); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Task not found.'); + }); + + it('should require authentication', async () => { + const response = await request(app) + .patch(`/api/task/${task.id}`) + .send({ name: 'Updated' }); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('DELETE /api/task/:id', () => { + let task; + + beforeEach(async () => { + task = await Task.create({ + name: 'Test Task', + user_id: user.id + }); + }); + + it('should delete task', async () => { + const response = await agent.delete(`/api/task/${task.id}`); + + expect(response.status).toBe(200); + expect(response.body.message).toBe('Task successfully deleted'); + + // Verify task is deleted + const deletedTask = await Task.findByPk(task.id); + expect(deletedTask).toBeNull(); + }); + + it('should return 404 for non-existent task', async () => { + const response = await agent.delete('/api/task/999999'); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Task not found.'); + }); + + it('should not allow deleting other user\'s tasks', async () => { + const bcrypt = require('bcrypt'); + const otherUser = await User.create({ + email: 'other@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + const otherTask = await Task.create({ + name: 'Other Task', + user_id: otherUser.id + }); + + const response = await agent.delete(`/api/task/${otherTask.id}`); + + expect(response.status).toBe(404); + expect(response.body.error).toBe('Task not found.'); + }); + + it('should require authentication', async () => { + const response = await request(app).delete(`/api/task/${task.id}`); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('Task with tags', () => { + it('should create task with tags', async () => { + const taskData = { + name: 'Test Task', + tags: [ + { name: 'work' }, + { name: 'urgent' } + ] + }; + + const response = await agent + .post('/api/task') + .send(taskData); + + expect(response.status).toBe(201); + expect(response.body.Tags).toBeDefined(); + expect(response.body.Tags.length).toBe(2); + expect(response.body.Tags.map(t => t.name)).toContain('work'); + expect(response.body.Tags.map(t => t.name)).toContain('urgent'); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/integration/telegram.test.js b/backend/tests/integration/telegram.test.js new file mode 100644 index 0000000..d7972e1 --- /dev/null +++ b/backend/tests/integration/telegram.test.js @@ -0,0 +1,152 @@ +const request = require('supertest'); +const app = require('../../app'); +const { User } = require('../../models'); +const { createTestUser } = require('../helpers/testUtils'); + +describe('Telegram Routes', () => { + let user, agent; + + beforeEach(async () => { + user = await createTestUser({ + email: 'test@example.com' + }); + + // Create authenticated agent + agent = request.agent(app); + await agent + .post('/api/login') + .send({ + email: 'test@example.com', + password: 'password123' + }); + }); + + describe('POST /api/telegram/setup', () => { + it('should setup telegram bot token', async () => { + const botToken = '123456789:ABCdefGHIjklMNOPQRSTUVwxyz-12345678'; + + const response = await agent + .post('/api/telegram/setup') + .send({ token: botToken }); + + expect(response.status).toBe(200); + expect(response.body.message).toBe('Telegram bot token updated successfully'); + + // Verify token was saved to user + const updatedUser = await User.findByPk(user.id); + expect(updatedUser.telegram_bot_token).toBe(botToken); + }); + + it('should require authentication', async () => { + const response = await request(app) + .post('/api/telegram/setup') + .send({ token: '123456789:ABCdefGHIjklMNOPQRSTUVwxyz-1234567890' }); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + + it('should require token parameter', async () => { + const response = await agent + .post('/api/telegram/setup') + .send({}); + + expect(response.status).toBe(400); + expect(response.body.error).toBe('Telegram bot token is required.'); + }); + + it('should validate token format', async () => { + const response = await agent + .post('/api/telegram/setup') + .send({ token: 'invalid-token-format' }); + + expect(response.status).toBe(400); + expect(response.body.error).toBe('Invalid Telegram bot token format.'); + }); + + it('should validate token format with correct pattern', async () => { + // Test various invalid formats + const invalidTokens = [ + '123456:short', + 'notnum:ABCdefGHIjklMNOPQRSTUVwxyz-12345678', + '123456789-ABCdefGHIjklMNOPQRSTUVwxyz-12345678', + '123456789:', + ':ABCdefGHIjklMNOPQRSTUVwxyz-12345678' + ]; + + for (const token of invalidTokens) { + const response = await agent + .post('/api/telegram/setup') + .send({ token }); + + expect(response.status).toBe(400); + expect(response.body.error).toBe('Invalid Telegram bot token format.'); + } + }); + + it('should accept valid token formats', async () => { + const validTokens = [ + '123456789:ABCdefGHIjklMNOPQRSTUVwxyz-12345678', + '987654321:XYZabcDEFghiJKLmnoPQRstUVW_09876543', + '555555555:abcdefghijklmnopqrstuvwxyzABCDEFGHI' + ]; + + for (const token of validTokens) { + const response = await agent + .post('/api/telegram/setup') + .send({ token }); + + expect(response.status).toBe(200); + expect(response.body.message).toBe('Telegram bot token updated successfully'); + } + }); + }); + + describe('POST /api/telegram/start-polling', () => { + beforeEach(async () => { + // Setup bot token first + await user.update({ + telegram_bot_token: '123456789:ABCdefGHIjklMNOPQRSTUVwxyz-12345678' + }); + }); + + it('should require authentication', async () => { + const response = await request(app) + .post('/api/telegram/start-polling'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + + it('should require bot token to be configured', async () => { + // Remove bot token + await user.update({ telegram_bot_token: null }); + + const response = await agent + .post('/api/telegram/start-polling'); + + expect(response.status).toBe(400); + expect(response.body.error).toBe('Telegram bot token not set.'); + }); + }); + + describe('POST /api/telegram/stop-polling', () => { + it('should require authentication', async () => { + const response = await request(app) + .post('/api/telegram/stop-polling'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); + + describe('GET /api/telegram/polling-status', () => { + it('should require authentication', async () => { + const response = await request(app) + .get('/api/telegram/polling-status'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/integration/url.test.js b/backend/tests/integration/url.test.js new file mode 100644 index 0000000..0de3ea6 --- /dev/null +++ b/backend/tests/integration/url.test.js @@ -0,0 +1,178 @@ +const request = require('supertest'); +const app = require('../../app'); +const { createTestUser } = require('../helpers/testUtils'); + +describe('URL Routes', () => { + let user, agent; + + beforeEach(async () => { + user = await createTestUser({ + email: 'test@example.com' + }); + + // Create authenticated agent + agent = request.agent(app); + await agent + .post('/api/login') + .send({ + email: 'test@example.com', + password: 'password123' + }); + }); + + describe('GET /api/url/title', () => { + it('should require authentication', async () => { + const response = await request(app) + .get('/api/url/title') + .query({ url: 'https://example.com' }); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + + it('should require url parameter', async () => { + const response = await agent + .get('/api/url/title'); + + expect(response.status).toBe(400); + expect(response.body.error).toBe('URL parameter is required'); + }); + + it('should return title for valid URL', async () => { + const response = await agent + .get('/api/url/title') + .query({ url: 'https://httpbin.org/html' }); + + expect(response.status).toBe(200); + expect(response.body).toHaveProperty('url'); + expect(response.body).toHaveProperty('title'); + expect(response.body.url).toBe('https://httpbin.org/html'); + // Title could be extracted or null depending on network conditions + expect(typeof response.body.title === 'string' || response.body.title === null).toBe(true); + }, 10000); + + it('should handle URL without protocol', async () => { + const response = await agent + .get('/api/url/title') + .query({ url: 'httpbin.org/html' }); + + expect(response.status).toBe(200); + expect(response.body).toHaveProperty('url'); + expect(response.body).toHaveProperty('title'); + expect(response.body.url).toBe('httpbin.org/html'); + // Title could be extracted or null depending on network conditions + expect(typeof response.body.title === 'string' || response.body.title === null).toBe(true); + }, 10000); + + it('should handle invalid URL gracefully', async () => { + const response = await agent + .get('/api/url/title') + .query({ url: 'not-a-valid-url' }); + + expect(response.status).toBe(200); + expect(response.body).toHaveProperty('url'); + expect(response.body).toHaveProperty('title'); + expect(response.body.url).toBe('not-a-valid-url'); + // Title could be null or error message + expect(response.body.title === null || typeof response.body.title === 'string').toBe(true); + }); + + it('should handle unreachable URL', async () => { + const response = await agent + .get('/api/url/title') + .query({ url: 'https://nonexistent-domain-12345.com' }); + + expect(response.status).toBe(200); + expect(response.body).toHaveProperty('url'); + expect(response.body).toHaveProperty('title'); + expect(response.body.url).toBe('https://nonexistent-domain-12345.com'); + expect(response.body.title).toBe(null); + }); + }); + + describe('POST /api/url/extract-from-text', () => { + it('should require authentication', async () => { + const response = await request(app) + .post('/api/url/extract-from-text') + .send({ text: 'Check out https://example.com' }); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + + it('should require text parameter', async () => { + const response = await agent + .post('/api/url/extract-from-text') + .send({}); + + expect(response.status).toBe(400); + expect(response.body.error).toBe('Text parameter is required'); + }); + + it('should extract URL from text and get title', async () => { + const testText = 'Check out this interesting site: https://httpbin.org/html'; + const response = await agent + .post('/api/url/extract-from-text') + .send({ text: testText }); + + expect(response.status).toBe(200); + expect(response.body.found).toBe(true); + expect(response.body.url).toBe('https://httpbin.org/html'); + expect(response.body.originalText).toBe(testText); + expect(response.body).toHaveProperty('title'); + // Title could be extracted or null depending on network conditions + expect(typeof response.body.title === 'string' || response.body.title === null).toBe(true); + }, 10000); + + it('should extract first URL when multiple URLs in text', async () => { + const testText = 'Check out https://httpbin.org/html and also https://example.com'; + const response = await agent + .post('/api/url/extract-from-text') + .send({ text: testText }); + + expect(response.status).toBe(200); + expect(response.body.found).toBe(true); + expect(response.body.url).toBe('https://httpbin.org/html'); + expect(response.body.originalText).toBe(testText); + expect(response.body).toHaveProperty('title'); + }, 10000); + + it('should return found false for URL without protocol', async () => { + const testText = 'Visit httpbin.org/html for testing'; + const response = await agent + .post('/api/url/extract-from-text') + .send({ text: testText }); + + expect(response.status).toBe(200); + expect(response.body.found).toBe(false); + }); + + it('should return found false when no URL in text', async () => { + const testText = 'This text has no URLs in it at all'; + const response = await agent + .post('/api/url/extract-from-text') + .send({ text: testText }); + + expect(response.status).toBe(200); + expect(response.body.found).toBe(false); + }); + + it('should handle empty text', async () => { + const response = await agent + .post('/api/url/extract-from-text') + .send({ text: '' }); + + expect(response.status).toBe(400); + expect(response.body.error).toBe('Text parameter is required'); + }); + + it('should handle text with only whitespace', async () => { + const response = await agent + .post('/api/url/extract-from-text') + .send({ text: ' \n\t ' }); + + expect(response.status).toBe(200); + expect(response.body.found).toBe(false); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/integration/users.test.js b/backend/tests/integration/users.test.js new file mode 100644 index 0000000..cec9aeb --- /dev/null +++ b/backend/tests/integration/users.test.js @@ -0,0 +1,283 @@ +const request = require('supertest'); +const app = require('../../app'); +const { User } = require('../../models'); +const { createTestUser } = require('../helpers/testUtils'); + +describe('Users Routes', () => { + let user, agent; + + beforeEach(async () => { + user = await createTestUser({ + email: 'test@example.com' + }); + + // Create authenticated agent + agent = request.agent(app); + await agent + .post('/api/login') + .send({ + email: 'test@example.com', + password: 'password123' + }); + }); + + describe('GET /api/profile', () => { + it('should get user profile', async () => { + const response = await agent.get('/api/profile'); + + expect(response.status).toBe(200); + expect(response.body.id).toBe(user.id); + expect(response.body.email).toBe(user.email); + expect(response.body).toHaveProperty('appearance'); + expect(response.body).toHaveProperty('language'); + expect(response.body).toHaveProperty('timezone'); + expect(response.body).toHaveProperty('avatar_image'); + expect(response.body).toHaveProperty('telegram_bot_token'); + expect(response.body).toHaveProperty('telegram_chat_id'); + expect(response.body).toHaveProperty('task_summary_enabled'); + expect(response.body).toHaveProperty('task_summary_frequency'); + }); + + it('should require authentication', async () => { + const response = await request(app).get('/api/profile'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + + it('should return 401 when session user no longer exists', async () => { + await User.destroy({ where: { id: user.id } }); + + const response = await agent.get('/api/profile'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('User not found'); + }); + }); + + describe('PATCH /api/profile', () => { + it('should update user profile', async () => { + const updateData = { + appearance: 'dark', + language: 'es', + timezone: 'UTC', + avatar_image: 'new-avatar.png', + telegram_bot_token: 'new-token' + }; + + const response = await agent + .patch('/api/profile') + .send(updateData); + + expect(response.status).toBe(200); + expect(response.body.appearance).toBe(updateData.appearance); + expect(response.body.language).toBe(updateData.language); + expect(response.body.timezone).toBe(updateData.timezone); + expect(response.body.avatar_image).toBe(updateData.avatar_image); + expect(response.body.telegram_bot_token).toBe(updateData.telegram_bot_token); + }); + + it('should allow partial updates', async () => { + const updateData = { + appearance: 'dark' + }; + + const response = await agent + .patch('/api/profile') + .send(updateData); + + expect(response.status).toBe(200); + expect(response.body.appearance).toBe(updateData.appearance); + expect(response.body.language).toBe(user.language); + }); + + it('should require authentication', async () => { + const updateData = { + appearance: 'dark' + }; + + const response = await request(app) + .patch('/api/profile') + .send(updateData); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + + it('should return 401 when session user no longer exists', async () => { + await User.destroy({ where: { id: user.id } }); + + const response = await agent + .patch('/api/profile') + .send({ appearance: 'dark' }); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('User not found'); + }); + }); + + describe('POST /api/profile/task-summary/toggle', () => { + beforeEach(async () => { + await user.update({ task_summary_enabled: false }); + }); + + it('should toggle task summary on', async () => { + const response = await agent.post('/api/profile/task-summary/toggle'); + + expect(response.status).toBe(200); + expect(response.body.success).toBe(true); + expect(response.body.enabled).toBe(true); + expect(response.body.message).toBe('Task summary notifications have been enabled.'); + }); + + it('should toggle task summary off', async () => { + await user.update({ task_summary_enabled: true }); + + const response = await agent.post('/api/profile/task-summary/toggle'); + + expect(response.status).toBe(200); + expect(response.body.success).toBe(true); + expect(response.body.enabled).toBe(false); + expect(response.body.message).toBe('Task summary notifications have been disabled.'); + }); + + it('should require authentication', async () => { + const response = await request(app).post('/api/profile/task-summary/toggle'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + + it('should return 401 when session user no longer exists', async () => { + await User.destroy({ where: { id: user.id } }); + + const response = await agent.post('/api/profile/task-summary/toggle'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('User not found'); + }); + }); + + describe('POST /api/profile/task-summary/frequency', () => { + it('should update task summary frequency', async () => { + const response = await agent + .post('/api/profile/task-summary/frequency') + .send({ frequency: 'daily' }); + + expect(response.status).toBe(200); + expect(response.body.success).toBe(true); + expect(response.body.frequency).toBe('daily'); + expect(response.body.message).toBe('Task summary frequency has been set to daily.'); + }); + + it('should require frequency parameter', async () => { + const response = await agent + .post('/api/profile/task-summary/frequency') + .send({}); + + expect(response.status).toBe(400); + expect(response.body.error).toBe('Frequency is required.'); + }); + + it('should validate frequency value', async () => { + const response = await agent + .post('/api/profile/task-summary/frequency') + .send({ frequency: 'invalid' }); + + expect(response.status).toBe(400); + expect(response.body.error).toBe('Invalid frequency value.'); + }); + + it('should accept valid frequencies', async () => { + const validFrequencies = ['daily', 'weekdays', 'weekly', '1h', '2h', '4h', '8h', '12h']; + + for (const frequency of validFrequencies) { + const response = await agent + .post('/api/profile/task-summary/frequency') + .send({ frequency }); + + expect(response.status).toBe(200); + expect(response.body.frequency).toBe(frequency); + } + }); + + it('should require authentication', async () => { + const response = await request(app) + .post('/api/profile/task-summary/frequency') + .send({ frequency: 'daily' }); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + + it('should return 401 when session user no longer exists', async () => { + await User.destroy({ where: { id: user.id } }); + + const response = await agent + .post('/api/profile/task-summary/frequency') + .send({ frequency: 'daily' }); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('User not found'); + }); + }); + + describe('POST /api/profile/task-summary/send-now', () => { + it('should require telegram configuration', async () => { + const response = await agent.post('/api/profile/task-summary/send-now'); + + expect(response.status).toBe(400); + expect(response.body.error).toBe('Telegram bot is not properly configured.'); + }); + + it('should require authentication', async () => { + const response = await request(app).post('/api/profile/task-summary/send-now'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + + it('should return 401 when session user no longer exists', async () => { + await User.destroy({ where: { id: user.id } }); + + const response = await agent.post('/api/profile/task-summary/send-now'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('User not found'); + }); + }); + + describe('GET /api/profile/task-summary/status', () => { + it('should get task summary status', async () => { + await user.update({ + task_summary_enabled: true, + task_summary_frequency: 'daily' + }); + + const response = await agent.get('/api/profile/task-summary/status'); + + expect(response.status).toBe(200); + expect(response.body.success).toBe(true); + expect(response.body.enabled).toBe(true); + expect(response.body.frequency).toBe('daily'); + expect(response.body).toHaveProperty('last_run'); + expect(response.body).toHaveProperty('next_run'); + }); + + it('should require authentication', async () => { + const response = await request(app).get('/api/profile/task-summary/status'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('Authentication required'); + }); + + it('should return 401 when session user no longer exists', async () => { + await User.destroy({ where: { id: user.id } }); + + const response = await agent.get('/api/profile/task-summary/status'); + + expect(response.status).toBe(401); + expect(response.body.error).toBe('User not found'); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/unit/middleware/auth.test.js b/backend/tests/unit/middleware/auth.test.js new file mode 100644 index 0000000..92f45eb --- /dev/null +++ b/backend/tests/unit/middleware/auth.test.js @@ -0,0 +1,130 @@ +const { requireAuth } = require('../../../middleware/auth'); +const { User } = require('../../../models'); + +describe('Auth Middleware', () => { + let req, res, next; + + beforeEach(() => { + req = { + path: '/api/tasks', + session: {} + }; + res = { + status: jest.fn().mockReturnThis(), + json: jest.fn() + }; + next = jest.fn(); + }); + + it('should skip authentication for health check', async () => { + req.path = '/api/health'; + + await requireAuth(req, res, next); + + expect(next).toHaveBeenCalled(); + expect(res.status).not.toHaveBeenCalled(); + }); + + it('should skip authentication for login route', async () => { + req.path = '/api/login'; + + await requireAuth(req, res, next); + + expect(next).toHaveBeenCalled(); + expect(res.status).not.toHaveBeenCalled(); + }); + + it('should skip authentication for current_user route', async () => { + req.path = '/api/current_user'; + + await requireAuth(req, res, next); + + expect(next).toHaveBeenCalled(); + expect(res.status).not.toHaveBeenCalled(); + }); + + it('should return 401 if no session', async () => { + req.session = null; + + await requireAuth(req, res, next); + + expect(res.status).toHaveBeenCalledWith(401); + expect(res.json).toHaveBeenCalledWith({ error: 'Authentication required' }); + expect(next).not.toHaveBeenCalled(); + }); + + it('should return 401 if no userId in session', async () => { + req.session = {}; + + await requireAuth(req, res, next); + + expect(res.status).toHaveBeenCalledWith(401); + expect(res.json).toHaveBeenCalledWith({ error: 'Authentication required' }); + expect(next).not.toHaveBeenCalled(); + }); + + it('should return 401 and destroy session if user not found', async () => { + const bcrypt = require('bcrypt'); + const user = await User.create({ + email: 'test@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + req.session = { + userId: user.id + 1, // Non-existent user ID + destroy: jest.fn() + }; + + await requireAuth(req, res, next); + + expect(req.session.destroy).toHaveBeenCalled(); + expect(res.status).toHaveBeenCalledWith(401); + expect(res.json).toHaveBeenCalledWith({ error: 'User not found' }); + expect(next).not.toHaveBeenCalled(); + }); + + it('should set currentUser and call next for valid session', async () => { + const bcrypt = require('bcrypt'); + const user = await User.create({ + email: 'test@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + req.session = { + userId: user.id + }; + + await requireAuth(req, res, next); + + expect(req.currentUser).toBeDefined(); + expect(req.currentUser.id).toBe(user.id); + expect(req.currentUser.email).toBe(user.email); + expect(next).toHaveBeenCalled(); + expect(res.status).not.toHaveBeenCalled(); + }); + + it('should handle database errors', async () => { + // Mock console.error to suppress expected error log in test output + const originalConsoleError = console.error; + console.error = jest.fn(); + + // Mock User.findByPk to throw an error + const originalFindByPk = User.findByPk; + User.findByPk = jest.fn().mockRejectedValue(new Error('Database connection error')); + + req.session = { + userId: 123, + destroy: jest.fn() + }; + + await requireAuth(req, res, next); + + expect(res.status).toHaveBeenCalledWith(500); + expect(res.json).toHaveBeenCalledWith({ error: 'Authentication error' }); + expect(next).not.toHaveBeenCalled(); + + // Restore original methods + User.findByPk = originalFindByPk; + console.error = originalConsoleError; + }); +}); \ No newline at end of file diff --git a/backend/tests/unit/models/area.test.js b/backend/tests/unit/models/area.test.js new file mode 100644 index 0000000..f4eb012 --- /dev/null +++ b/backend/tests/unit/models/area.test.js @@ -0,0 +1,74 @@ +const { Area, User } = require('../../../models'); + +describe('Area Model', () => { + let user; + + beforeEach(async () => { + const bcrypt = require('bcrypt'); + user = await User.create({ + email: 'test@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + }); + + describe('validation', () => { + it('should create an area with valid data', async () => { + const areaData = { + name: 'Work', + description: 'Work related projects', + user_id: user.id + }; + + const area = await Area.create(areaData); + + expect(area.name).toBe(areaData.name); + expect(area.description).toBe(areaData.description); + expect(area.user_id).toBe(user.id); + }); + + it('should require name', async () => { + const areaData = { + description: 'Area without name', + user_id: user.id + }; + + await expect(Area.create(areaData)).rejects.toThrow(); + }); + + it('should require user_id', async () => { + const areaData = { + name: 'Test Area' + }; + + await expect(Area.create(areaData)).rejects.toThrow(); + }); + + it('should allow null description', async () => { + const areaData = { + name: 'Test Area', + user_id: user.id, + description: null + }; + + const area = await Area.create(areaData); + expect(area.description).toBeNull(); + }); + }); + + describe('associations', () => { + it('should belong to a user', async () => { + const area = await Area.create({ + name: 'Test Area', + user_id: user.id + }); + + const areaWithUser = await Area.findByPk(area.id, { + include: [{ model: User }] + }); + + expect(areaWithUser.User).toBeDefined(); + expect(areaWithUser.User.id).toBe(user.id); + expect(areaWithUser.User.email).toBe(user.email); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/unit/models/inbox_item.test.js b/backend/tests/unit/models/inbox_item.test.js new file mode 100644 index 0000000..fa707b6 --- /dev/null +++ b/backend/tests/unit/models/inbox_item.test.js @@ -0,0 +1,96 @@ +const { InboxItem, User } = require('../../../models'); + +describe('InboxItem Model', () => { + let user; + + beforeEach(async () => { + const bcrypt = require('bcrypt'); + user = await User.create({ + email: 'test@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + }); + + describe('validation', () => { + it('should create an inbox item with valid data', async () => { + const inboxData = { + content: 'Remember to buy groceries', + status: 'added', + source: 'web', + user_id: user.id + }; + + const inboxItem = await InboxItem.create(inboxData); + + expect(inboxItem.content).toBe(inboxData.content); + expect(inboxItem.status).toBe(inboxData.status); + expect(inboxItem.source).toBe(inboxData.source); + expect(inboxItem.user_id).toBe(user.id); + }); + + it('should require content', async () => { + const inboxData = { + user_id: user.id + }; + + await expect(InboxItem.create(inboxData)).rejects.toThrow(); + }); + + it('should require user_id', async () => { + const inboxData = { + content: 'Test content' + }; + + await expect(InboxItem.create(inboxData)).rejects.toThrow(); + }); + + it('should require status', async () => { + const inboxData = { + content: 'Test content', + user_id: user.id, + status: null + }; + + await expect(InboxItem.create(inboxData)).rejects.toThrow(); + }); + + it('should require source', async () => { + const inboxData = { + content: 'Test content', + user_id: user.id, + source: null + }; + + await expect(InboxItem.create(inboxData)).rejects.toThrow(); + }); + }); + + describe('default values', () => { + it('should set correct default values', async () => { + const inboxItem = await InboxItem.create({ + content: 'Test content', + user_id: user.id + }); + + expect(inboxItem.status).toBe('added'); + expect(inboxItem.source).toBe('tududi'); + }); + }); + + describe('associations', () => { + it('should belong to a user', async () => { + const inboxItem = await InboxItem.create({ + content: 'Test content', + user_id: user.id + }); + + const inboxItemWithUser = await InboxItem.findByPk(inboxItem.id, { + include: [{ model: User }] + }); + + expect(inboxItemWithUser.User).toBeDefined(); + expect(inboxItemWithUser.User.id).toBe(user.id); + expect(inboxItemWithUser.User.email).toBe(user.email); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/unit/models/note.test.js b/backend/tests/unit/models/note.test.js new file mode 100644 index 0000000..bb08555 --- /dev/null +++ b/backend/tests/unit/models/note.test.js @@ -0,0 +1,102 @@ +const { Note, User, Project } = require('../../../models'); + +describe('Note Model', () => { + let user, project; + + beforeEach(async () => { + const bcrypt = require('bcrypt'); + user = await User.create({ + email: 'test@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + project = await Project.create({ + name: 'Test Project', + user_id: user.id + }); + }); + + describe('validation', () => { + it('should create a note with valid data', async () => { + const noteData = { + title: 'Test Note', + content: 'This is a test note content', + user_id: user.id, + project_id: project.id + }; + + const note = await Note.create(noteData); + + expect(note.title).toBe(noteData.title); + expect(note.content).toBe(noteData.content); + expect(note.user_id).toBe(user.id); + expect(note.project_id).toBe(project.id); + }); + + it('should require user_id', async () => { + const noteData = { + title: 'Test Note', + content: 'Test content' + }; + + await expect(Note.create(noteData)).rejects.toThrow(); + }); + + it('should allow title and content to be null', async () => { + const noteData = { + title: null, + content: null, + user_id: user.id + }; + + const note = await Note.create(noteData); + expect(note.title).toBeNull(); + expect(note.content).toBeNull(); + }); + + it('should allow project_id to be null', async () => { + const noteData = { + title: 'Test Note', + content: 'Test content', + user_id: user.id, + project_id: null + }; + + const note = await Note.create(noteData); + expect(note.project_id).toBeNull(); + }); + }); + + describe('associations', () => { + it('should belong to a user', async () => { + const note = await Note.create({ + title: 'Test Note', + user_id: user.id + }); + + const noteWithUser = await Note.findByPk(note.id, { + include: [{ model: User }] + }); + + expect(noteWithUser.User).toBeDefined(); + expect(noteWithUser.User.id).toBe(user.id); + expect(noteWithUser.User.email).toBe(user.email); + }); + + it('should belong to a project', async () => { + const note = await Note.create({ + title: 'Test Note', + user_id: user.id, + project_id: project.id + }); + + const noteWithProject = await Note.findByPk(note.id, { + include: [{ model: Project }] + }); + + expect(noteWithProject.Project).toBeDefined(); + expect(noteWithProject.Project.id).toBe(project.id); + expect(noteWithProject.Project.name).toBe(project.name); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/unit/models/project.test.js b/backend/tests/unit/models/project.test.js new file mode 100644 index 0000000..55af80d --- /dev/null +++ b/backend/tests/unit/models/project.test.js @@ -0,0 +1,141 @@ +const { Project, User, Area } = require('../../../models'); + +describe('Project Model', () => { + let user, area; + + beforeEach(async () => { + const bcrypt = require('bcrypt'); + user = await User.create({ + email: 'test@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + area = await Area.create({ + name: 'Work', + user_id: user.id + }); + }); + + describe('validation', () => { + it('should create a project with valid data', async () => { + const projectData = { + name: 'Test Project', + description: 'Test Description', + active: true, + pin_to_sidebar: false, + priority: 1, + user_id: user.id, + area_id: area.id + }; + + const project = await Project.create(projectData); + + expect(project.name).toBe(projectData.name); + expect(project.description).toBe(projectData.description); + expect(project.active).toBe(projectData.active); + expect(project.pin_to_sidebar).toBe(projectData.pin_to_sidebar); + expect(project.priority).toBe(projectData.priority); + expect(project.user_id).toBe(user.id); + expect(project.area_id).toBe(area.id); + }); + + it('should require name', async () => { + const projectData = { + description: 'Project without name', + user_id: user.id + }; + + await expect(Project.create(projectData)).rejects.toThrow(); + }); + + it('should require user_id', async () => { + const projectData = { + name: 'Test Project' + }; + + await expect(Project.create(projectData)).rejects.toThrow(); + }); + + it('should validate priority range', async () => { + const projectData = { + name: 'Test Project', + user_id: user.id, + priority: 5 + }; + + await expect(Project.create(projectData)).rejects.toThrow(); + }); + + it('should allow valid priority values', async () => { + for (let priority of [0, 1, 2]) { + const project = await Project.create({ + name: `Test Project ${priority}`, + user_id: user.id, + priority: priority + }); + expect(project.priority).toBe(priority); + } + }); + }); + + describe('default values', () => { + it('should set correct default values', async () => { + const project = await Project.create({ + name: 'Test Project', + user_id: user.id + }); + + expect(project.active).toBe(false); + expect(project.pin_to_sidebar).toBe(false); + }); + }); + + describe('optional fields', () => { + it('should allow optional fields to be null', async () => { + const project = await Project.create({ + name: 'Test Project', + user_id: user.id, + description: null, + priority: null, + due_date_at: null, + area_id: null + }); + + expect(project.description).toBeNull(); + expect(project.priority).toBeNull(); + expect(project.due_date_at).toBeNull(); + expect(project.area_id).toBeNull(); + }); + }); + + describe('associations', () => { + it('should belong to a user', async () => { + const project = await Project.create({ + name: 'Test Project', + user_id: user.id + }); + + const projectWithUser = await Project.findByPk(project.id, { + include: [{ model: User }] + }); + + expect(projectWithUser.User).toBeDefined(); + expect(projectWithUser.User.id).toBe(user.id); + }); + + it('should belong to an area', async () => { + const project = await Project.create({ + name: 'Test Project', + user_id: user.id, + area_id: area.id + }); + + const projectWithArea = await Project.findByPk(project.id, { + include: [{ model: Area }] + }); + + expect(projectWithArea.Area).toBeDefined(); + expect(projectWithArea.Area.id).toBe(area.id); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/unit/models/tag.test.js b/backend/tests/unit/models/tag.test.js new file mode 100644 index 0000000..9a334f3 --- /dev/null +++ b/backend/tests/unit/models/tag.test.js @@ -0,0 +1,83 @@ +const { Tag, User } = require('../../../models'); + +describe('Tag Model', () => { + let user; + + beforeEach(async () => { + const bcrypt = require('bcrypt'); + user = await User.create({ + email: 'test@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + }); + + describe('validation', () => { + it('should create a tag with valid data', async () => { + const tagData = { + name: 'work', + user_id: user.id + }; + + const tag = await Tag.create(tagData); + + expect(tag.name).toBe(tagData.name); + expect(tag.user_id).toBe(user.id); + }); + + it('should require name', async () => { + const tagData = { + user_id: user.id + }; + + await expect(Tag.create(tagData)).rejects.toThrow(); + }); + + it('should require user_id', async () => { + const tagData = { + name: 'work' + }; + + await expect(Tag.create(tagData)).rejects.toThrow(); + }); + + it('should allow multiple tags with same name for different users', async () => { + const bcrypt = require('bcrypt'); + const otherUser = await User.create({ + email: 'other@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + const tag1 = await Tag.create({ + name: 'work', + user_id: user.id + }); + + const tag2 = await Tag.create({ + name: 'work', + user_id: otherUser.id + }); + + expect(tag1.name).toBe('work'); + expect(tag2.name).toBe('work'); + expect(tag1.user_id).toBe(user.id); + expect(tag2.user_id).toBe(otherUser.id); + }); + }); + + describe('associations', () => { + it('should belong to a user', async () => { + const tag = await Tag.create({ + name: 'work', + user_id: user.id + }); + + const tagWithUser = await Tag.findByPk(tag.id, { + include: [{ model: User }] + }); + + expect(tagWithUser.User).toBeDefined(); + expect(tagWithUser.User.id).toBe(user.id); + expect(tagWithUser.User.email).toBe(user.email); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/unit/models/task.test.js b/backend/tests/unit/models/task.test.js new file mode 100644 index 0000000..d8a9ffb --- /dev/null +++ b/backend/tests/unit/models/task.test.js @@ -0,0 +1,183 @@ +const { Task, User } = require('../../../models'); + +describe('Task Model', () => { + let user; + + beforeEach(async () => { + const bcrypt = require('bcrypt'); + user = await User.create({ + email: 'test@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + }); + + describe('validation', () => { + it('should create a task with valid data', async () => { + const taskData = { + name: 'Test Task', + description: 'Test Description', + user_id: user.id + }; + + const task = await Task.create(taskData); + + expect(task.name).toBe(taskData.name); + expect(task.description).toBe(taskData.description); + expect(task.user_id).toBe(user.id); + expect(task.today).toBe(false); + expect(task.priority).toBe(0); + expect(task.status).toBe(0); + expect(task.recurrence_type).toBe('none'); + }); + + it('should require name', async () => { + const taskData = { + user_id: user.id + }; + + await expect(Task.create(taskData)).rejects.toThrow(); + }); + + it('should require user_id', async () => { + const taskData = { + name: 'Test Task' + }; + + await expect(Task.create(taskData)).rejects.toThrow(); + }); + + it('should validate priority range', async () => { + const taskData = { + name: 'Test Task', + user_id: user.id, + priority: 5 + }; + + await expect(Task.create(taskData)).rejects.toThrow(); + }); + + it('should validate status range', async () => { + const taskData = { + name: 'Test Task', + user_id: user.id, + status: 10 + }; + + await expect(Task.create(taskData)).rejects.toThrow(); + }); + }); + + describe('constants', () => { + it('should have correct priority constants', () => { + expect(Task.PRIORITY.LOW).toBe(0); + expect(Task.PRIORITY.MEDIUM).toBe(1); + expect(Task.PRIORITY.HIGH).toBe(2); + }); + + it('should have correct status constants', () => { + expect(Task.STATUS.NOT_STARTED).toBe(0); + expect(Task.STATUS.IN_PROGRESS).toBe(1); + expect(Task.STATUS.DONE).toBe(2); + expect(Task.STATUS.ARCHIVED).toBe(3); + expect(Task.STATUS.WAITING).toBe(4); + }); + }); + + describe('instance methods', () => { + let task; + + beforeEach(async () => { + task = await Task.create({ + name: 'Test Task', + user_id: user.id + }); + }); + + it('should return correct priority name', async () => { + task.priority = Task.PRIORITY.LOW; + expect(task.getPriorityName()).toBe('low'); + + task.priority = Task.PRIORITY.MEDIUM; + expect(task.getPriorityName()).toBe('medium'); + + task.priority = Task.PRIORITY.HIGH; + expect(task.getPriorityName()).toBe('high'); + }); + + it('should return correct status name', async () => { + task.status = Task.STATUS.NOT_STARTED; + expect(task.getStatusName()).toBe('not_started'); + + task.status = Task.STATUS.IN_PROGRESS; + expect(task.getStatusName()).toBe('in_progress'); + + task.status = Task.STATUS.DONE; + expect(task.getStatusName()).toBe('done'); + + task.status = Task.STATUS.ARCHIVED; + expect(task.getStatusName()).toBe('archived'); + + task.status = Task.STATUS.WAITING; + expect(task.getStatusName()).toBe('waiting'); + }); + }); + + describe('default values', () => { + it('should set correct default values', async () => { + const task = await Task.create({ + name: 'Test Task', + user_id: user.id + }); + + expect(task.today).toBe(false); + expect(task.priority).toBe(0); + expect(task.status).toBe(0); + expect(task.recurrence_type).toBe('none'); + }); + }); + + describe('optional fields', () => { + it('should allow optional fields to be null', async () => { + const task = await Task.create({ + name: 'Test Task', + user_id: user.id, + description: null, + due_date: null, + note: null, + recurrence_interval: null, + recurrence_end_date: null, + last_generated_date: null, + project_id: null + }); + + expect(task.description).toBeNull(); + expect(task.due_date).toBeNull(); + expect(task.note).toBeNull(); + expect(task.recurrence_interval).toBeNull(); + expect(task.recurrence_end_date).toBeNull(); + expect(task.last_generated_date).toBeNull(); + expect(task.project_id).toBeNull(); + }); + + it('should accept optional field values', async () => { + const dueDate = new Date(); + const task = await Task.create({ + name: 'Test Task', + description: 'Test Description', + due_date: dueDate, + today: true, + priority: Task.PRIORITY.HIGH, + status: Task.STATUS.IN_PROGRESS, + note: 'Test Note', + user_id: user.id + }); + + expect(task.description).toBe('Test Description'); + expect(task.due_date).toEqual(dueDate); + expect(task.today).toBe(true); + expect(task.priority).toBe(Task.PRIORITY.HIGH); + expect(task.status).toBe(Task.STATUS.IN_PROGRESS); + expect(task.note).toBe('Test Note'); + }); + }); +}); \ No newline at end of file diff --git a/backend/tests/unit/models/user.test.js b/backend/tests/unit/models/user.test.js new file mode 100644 index 0000000..0ea4520 --- /dev/null +++ b/backend/tests/unit/models/user.test.js @@ -0,0 +1,135 @@ +const { User } = require('../../../models'); + +describe('User Model', () => { + describe('validation', () => { + it('should create a user with valid data', async () => { + const bcrypt = require('bcrypt'); + const userData = { + email: 'test@example.com', + password_digest: await bcrypt.hash('password123', 10) + }; + + const user = await User.create(userData); + + expect(user.email).toBe(userData.email); + expect(user.password_digest).toBeDefined(); + expect(user.password_digest).toBe(userData.password_digest); + expect(user.appearance).toBe('light'); + expect(user.language).toBe('en'); + expect(user.timezone).toBe('UTC'); + }); + + it('should require email', async () => { + const userData = { + password: 'password123' + }; + + await expect(User.create(userData)).rejects.toThrow(); + }); + + it('should require valid email format', async () => { + const userData = { + email: 'invalid-email', + password: 'password123' + }; + + await expect(User.create(userData)).rejects.toThrow(); + }); + + it('should require unique email', async () => { + const bcrypt = require('bcrypt'); + const userData = { + email: 'test@example.com', + password_digest: await bcrypt.hash('password123', 10) + }; + + await User.create(userData); + await expect(User.create(userData)).rejects.toThrow(); + }); + + it('should validate appearance values', async () => { + const userData = { + email: 'test@example.com', + password: 'password123', + appearance: 'invalid' + }; + + await expect(User.create(userData)).rejects.toThrow(); + }); + + it('should validate task_summary_frequency values', async () => { + const userData = { + email: 'test@example.com', + password: 'password123', + task_summary_frequency: 'invalid' + }; + + await expect(User.create(userData)).rejects.toThrow(); + }); + }); + + describe('password methods', () => { + let user; + + beforeEach(async () => { + const bcrypt = require('bcrypt'); + user = await User.create({ + email: 'test@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + }); + + it('should hash password on creation', async () => { + expect(user.password_digest).toBeDefined(); + expect(user.password_digest).not.toBe('password123'); + }); + + it('should check password correctly', async () => { + const isValid = await user.checkPassword('password123'); + expect(isValid).toBe(true); + + const isInvalid = await user.checkPassword('wrongpassword'); + expect(isInvalid).toBe(false); + }); + + it('should set new password using setPassword method', async () => { + const oldPasswordDigest = user.password_digest; + await user.setPassword('newpassword'); + + expect(user.password_digest).not.toBe(oldPasswordDigest); + + const isValidNew = await user.checkPassword('newpassword'); + expect(isValidNew).toBe(true); + + const isValidOld = await user.checkPassword('password123'); + expect(isValidOld).toBe(false); + }); + + it('should hash password on update', async () => { + const oldPasswordDigest = user.password_digest; + user.password = 'newpassword'; + await user.save(); + + expect(user.password_digest).not.toBe(oldPasswordDigest); + + const isValidNew = await user.checkPassword('newpassword'); + expect(isValidNew).toBe(true); + }); + }); + + describe('default values', () => { + it('should set correct default values', async () => { + const bcrypt = require('bcrypt'); + const user = await User.create({ + email: 'test@example.com', + password_digest: await bcrypt.hash('password123', 10) + }); + + expect(user.appearance).toBe('light'); + expect(user.language).toBe('en'); + expect(user.timezone).toBe('UTC'); + expect(user.task_summary_enabled).toBe(false); + expect(user.task_summary_frequency).toBe('daily'); + }); + }); +}); \ No newline at end of file diff --git a/config.ru b/config.ru deleted file mode 100644 index 785bf5c..0000000 --- a/config.ru +++ /dev/null @@ -1,2 +0,0 @@ -require './app' -run Sinatra::Application \ No newline at end of file diff --git a/config/initializers/scheduler.rb b/config/initializers/scheduler.rb deleted file mode 100644 index f37bcaa..0000000 --- a/config/initializers/scheduler.rb +++ /dev/null @@ -1,184 +0,0 @@ -# config/initializers/scheduler.rb -require 'rufus-scheduler' -require_relative '../../app/services/task_summary_service' - -# Helper method to update user's summary tracking fields -def update_summary_tracking(user, next_time) - user.update( - task_summary_last_run: Time.now, - task_summary_next_run: next_time - ) -end - -# Don't schedule in test environment or when reloading in development -if ENV['RACK_ENV'] != 'test' && ENV['DISABLE_SCHEDULER'] != 'true' - scheduler = Rufus::Scheduler.singleton - - # Daily schedule at 7 AM (for users with daily frequency) - daily_job = scheduler.cron '0 7 * * *' do - puts "Running scheduled task: Daily task summary" - - User.where.not(telegram_bot_token: [nil, '']) - .where.not(telegram_chat_id: [nil, '']) - .where(task_summary_enabled: true) - .where(task_summary_frequency: 'daily') - .each do |user| - begin - TaskSummaryService.send_summary_to_user(user.id) - # Calculate next run time - tomorrow at 7 AM - next_run = Time.now.tomorrow.change(hour: 7, min: 0, sec: 0) - update_summary_tracking(user, next_run) - puts "Sent daily summary to user #{user.id}" - rescue => e - puts "Error sending daily summary to user #{user.id}: #{e.message}" - end - end - end - - # Weekdays schedule at 7 AM (Monday through Friday) - weekday_job = scheduler.cron '0 7 * * 1-5' do - puts "Running scheduled task: Weekday task summary" - - User.where.not(telegram_bot_token: [nil, '']) - .where.not(telegram_chat_id: [nil, '']) - .where(task_summary_enabled: true) - .where(task_summary_frequency: 'weekdays') - .each do |user| - begin - TaskSummaryService.send_summary_to_user(user.id) - # Calculate next run time - next weekday at 7 AM - current_day = Time.now.wday - days_until_next_weekday = current_day == 5 ? 3 : 1 # If Friday, next is Monday (+3 days), otherwise next day - next_run = Time.now.advance(days: days_until_next_weekday).change(hour: 7, min: 0, sec: 0) - update_summary_tracking(user, next_run) - puts "Sent weekday summary to user #{user.id}" - rescue => e - puts "Error sending weekday summary to user #{user.id}: #{e.message}" - end - end - end - - # Weekly schedule at 7 AM on Monday - weekly_job = scheduler.cron '0 7 * * 1' do - puts "Running scheduled task: Weekly task summary" - - User.where.not(telegram_bot_token: [nil, '']) - .where.not(telegram_chat_id: [nil, '']) - .where(task_summary_enabled: true) - .where(task_summary_frequency: 'weekly') - .each do |user| - begin - TaskSummaryService.send_summary_to_user(user.id) - # Calculate next run time - next Monday at 7 AM - next_run = Time.now.advance(days: 7).change(hour: 7, min: 0, sec: 0) - update_summary_tracking(user, next_run) - puts "Sent weekly summary to user #{user.id}" - rescue => e - puts "Error sending weekly summary to user #{user.id}: #{e.message}" - end - end - end - - # Hourly schedules for different intervals - - # Every 1 hour - hourly_job = scheduler.every '1h' do - puts "Running scheduled task: Hourly (1h) task summary" - - User.where.not(telegram_bot_token: [nil, '']) - .where.not(telegram_chat_id: [nil, '']) - .where(task_summary_enabled: true) - .where(task_summary_frequency: '1h') - .each do |user| - begin - TaskSummaryService.send_summary_to_user(user.id) - next_run = Time.now + 1.hour - update_summary_tracking(user, next_run) - puts "Sent hourly summary to user #{user.id}" - rescue => e - puts "Error sending hourly summary to user #{user.id}: #{e.message}" - end - end - end - - # Every 2 hours - two_hourly_job = scheduler.every '2h' do - puts "Running scheduled task: 2-hour task summary" - - User.where.not(telegram_bot_token: [nil, '']) - .where.not(telegram_chat_id: [nil, '']) - .where(task_summary_enabled: true) - .where(task_summary_frequency: '2h') - .each do |user| - begin - TaskSummaryService.send_summary_to_user(user.id) - next_run = Time.now + 2.hours - update_summary_tracking(user, next_run) - puts "Sent 2-hour summary to user #{user.id}" - rescue => e - puts "Error sending 2-hour summary to user #{user.id}: #{e.message}" - end - end - end - - # Every 4 hours - four_hourly_job = scheduler.every '4h' do - puts "Running scheduled task: 4-hour task summary" - - User.where.not(telegram_bot_token: [nil, '']) - .where.not(telegram_chat_id: [nil, '']) - .where(task_summary_enabled: true) - .where(task_summary_frequency: '4h') - .each do |user| - begin - TaskSummaryService.send_summary_to_user(user.id) - next_run = Time.now + 4.hours - update_summary_tracking(user, next_run) - puts "Sent 4-hour summary to user #{user.id}" - rescue => e - puts "Error sending 4-hour summary to user #{user.id}: #{e.message}" - end - end - end - - # Every 8 hours - eight_hourly_job = scheduler.every '8h' do - puts "Running scheduled task: 8-hour task summary" - - User.where.not(telegram_bot_token: [nil, '']) - .where.not(telegram_chat_id: [nil, '']) - .where(task_summary_enabled: true) - .where(task_summary_frequency: '8h') - .each do |user| - begin - TaskSummaryService.send_summary_to_user(user.id) - next_run = Time.now + 8.hours - update_summary_tracking(user, next_run) - puts "Sent 8-hour summary to user #{user.id}" - rescue => e - puts "Error sending 8-hour summary to user #{user.id}: #{e.message}" - end - end - end - - # Every 12 hours - twelve_hourly_job = scheduler.every '12h' do - puts "Running scheduled task: 12-hour task summary" - - User.where.not(telegram_bot_token: [nil, '']) - .where.not(telegram_chat_id: [nil, '']) - .where(task_summary_enabled: true) - .where(task_summary_frequency: '12h') - .each do |user| - begin - TaskSummaryService.send_summary_to_user(user.id) - next_run = Time.now + 12.hours - update_summary_tracking(user, next_run) - puts "Sent 12-hour summary to user #{user.id}" - rescue => e - puts "Error sending 12-hour summary to user #{user.id}: #{e.message}" - end - end - end -end - diff --git a/config/initializers/telegram_initializer.rb b/config/initializers/telegram_initializer.rb deleted file mode 100644 index 3953812..0000000 --- a/config/initializers/telegram_initializer.rb +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env ruby -# config/initializers/telegram_initializer.rb -require_relative '../../app/routes/telegram_poller' -require_relative '../../app/models/user' - -# Create a method to be called after database connection is established -def initialize_telegram_polling - if ENV['RACK_ENV'] != 'test' && ENV['DISABLE_TELEGRAM'] != 'true' - puts "Initializing Telegram polling for configured users..." - - # Get singleton instance of the poller - poller = TelegramPoller.instance - - # Make sure we have a database connection - begin - ActiveRecord::Base.connection_pool.with_connection do |connection| - # Check if the users table exists - if connection.table_exists?('users') - begin - # Find users with configured Telegram tokens - users_with_telegram = User.where.not(telegram_bot_token: [nil, '']) - - if users_with_telegram.any? - puts "Found #{users_with_telegram.count} users with Telegram configuration" - - # Add each user to the polling list - users_with_telegram.each do |user| - puts "Starting Telegram polling for user #{user.id}" - poller.add_user(user) - end - - puts "Telegram polling initialized successfully" - else - puts "No users with Telegram configuration found" - end - rescue => e - puts "Error initializing Telegram polling: #{e.message}" - puts e.backtrace.join("\n") - end - else - puts "Users table doesn't exist yet, skipping Telegram initialization" - end - end - rescue => e - puts "Database connection not available for Telegram initialization: #{e.message}" - puts "Telegram polling will be initialized later when the database is available." - end - end -end - -# Don't run the initializer here - we'll hook it into the Sinatra app after ActiveRecord is initialized \ No newline at end of file diff --git a/console.rb b/console.rb deleted file mode 100644 index 60e67a3..0000000 --- a/console.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'irb' -require './app' - -IRB.start diff --git a/cookies.txt b/cookies.txt deleted file mode 100644 index f894453..0000000 --- a/cookies.txt +++ /dev/null @@ -1,5 +0,0 @@ -# Netscape HTTP Cookie File -# https://curl.se/docs/http-cookies.html -# This file was generated by libcurl! Edit at your own risk. - -#HttpOnly_localhost FALSE / FALSE 1752327280 rack.session U6U152aP%2F1FvgHP%2BTqOI6ZFNAriX8YWVIlXFp6FFPuOc%2FBgNnbDCJdfBfkC6p6gVikrYfiVd17qZenOEAlYZFpDlg0nzPJZqCYxgc9bhu4o3QOdUrEEYLu5ryVLUxh7DdLd7OVrMt2yHk3wixuky0icIpTw5%2Bc4dxeh4Vt0cBvy4fQasw0FZfvAjbyaYCAlE7dqE5WZ5o1dT5xEbwCEH3JO14oPmta2xf%2Bx3PJjyvZCLh3Ipxm8%2F6qlCLUC0HNQa6NgRL7ak71bDj7e7NLQ%3D--rOzyGipe0E8%2BPtPC--lRaDcnZWXd1CIpbvnCLxJA%3D%3D diff --git a/create_migration.sh b/create_migration.sh deleted file mode 100755 index acebe29..0000000 --- a/create_migration.sh +++ /dev/null @@ -1,3 +0,0 @@ -#! /bin/bash - -bundle exec ../bin/rake db:create_migration "$1" \ No newline at end of file diff --git a/db/migrate/20231107102451_create_users.rb b/db/migrate/20231107102451_create_users.rb deleted file mode 100644 index 9311a4b..0000000 --- a/db/migrate/20231107102451_create_users.rb +++ /dev/null @@ -1,11 +0,0 @@ -class CreateUsers < ActiveRecord::Migration[7.1] - def change - create_table :users do |t| - t.string :name - t.string :email - t.string :password_digest - - t.timestamps null: false - end - end -end diff --git a/db/migrate/20231107102516_create_areas.rb b/db/migrate/20231107102516_create_areas.rb deleted file mode 100644 index 8bf364d..0000000 --- a/db/migrate/20231107102516_create_areas.rb +++ /dev/null @@ -1,10 +0,0 @@ -class CreateAreas < ActiveRecord::Migration[7.1] - def change - create_table :areas do |t| - t.string :name - t.references :user, null: false, foreign_key: true - - t.timestamps null: false - end - end -end diff --git a/db/migrate/20231107102609_create_projects.rb b/db/migrate/20231107102609_create_projects.rb deleted file mode 100644 index 8d99e5e..0000000 --- a/db/migrate/20231107102609_create_projects.rb +++ /dev/null @@ -1,11 +0,0 @@ -class CreateProjects < ActiveRecord::Migration[7.1] - def change - create_table :projects do |t| - t.string :name - t.references :user, null: false, foreign_key: true - t.references :area, foreign_key: true - - t.timestamps null: false - end - end -end diff --git a/db/migrate/20231107102631_create_tasks.rb b/db/migrate/20231107102631_create_tasks.rb deleted file mode 100644 index fe46d60..0000000 --- a/db/migrate/20231107102631_create_tasks.rb +++ /dev/null @@ -1,13 +0,0 @@ -class CreateTasks < ActiveRecord::Migration[7.1] - def change - create_table :tasks do |t| - t.string :name - t.string :priority - t.datetime :due_date - t.references :user, null: false, foreign_key: true - t.references :project, foreign_key: true - - t.timestamps null: false - end - end -end diff --git a/db/migrate/20231109055429_add_fields_to_tasks.rb b/db/migrate/20231109055429_add_fields_to_tasks.rb deleted file mode 100644 index 9878868..0000000 --- a/db/migrate/20231109055429_add_fields_to_tasks.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AddFieldsToTasks < ActiveRecord::Migration[7.1] - def change - add_column :tasks, :today, :boolean, default: false - add_column :tasks, :description, :text - add_column :tasks, :completed, :boolean, default: false - end -end diff --git a/db/migrate/20231109055533_add_fields_to_projects.rb b/db/migrate/20231109055533_add_fields_to_projects.rb deleted file mode 100644 index d940a86..0000000 --- a/db/migrate/20231109055533_add_fields_to_projects.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddFieldsToProjects < ActiveRecord::Migration[7.1] - def change - add_column :projects, :description, :text - end -end diff --git a/db/migrate/20231110163101_add_cascade_delete_to_projects_and_tasks.rb b/db/migrate/20231110163101_add_cascade_delete_to_projects_and_tasks.rb deleted file mode 100644 index 822d9a7..0000000 --- a/db/migrate/20231110163101_add_cascade_delete_to_projects_and_tasks.rb +++ /dev/null @@ -1,9 +0,0 @@ -class AddCascadeDeleteToProjectsAndTasks < ActiveRecord::Migration[7.1] - def change - remove_foreign_key :projects, :areas - add_foreign_key :projects, :areas, on_delete: :cascade - - remove_foreign_key :tasks, :projects - add_foreign_key :tasks, :projects, on_delete: :cascade - end -end diff --git a/db/migrate/20231114203847_add_tags.rb b/db/migrate/20231114203847_add_tags.rb deleted file mode 100644 index a6401a7..0000000 --- a/db/migrate/20231114203847_add_tags.rb +++ /dev/null @@ -1,10 +0,0 @@ -class AddTags < ActiveRecord::Migration[7.1] - def change - create_table :tags do |t| - t.string :name - t.references :user, null: false, foreign_key: { on_delete: :cascade } - - t.timestamps - end - end -end diff --git a/db/migrate/20231114210336_create_tasks_tags.rb b/db/migrate/20231114210336_create_tasks_tags.rb deleted file mode 100644 index 12b6d4a..0000000 --- a/db/migrate/20231114210336_create_tasks_tags.rb +++ /dev/null @@ -1,8 +0,0 @@ -class CreateTasksTags < ActiveRecord::Migration[7.1] - def change - create_table :tasks_tags, id: false do |t| - t.belongs_to :task, null: false, foreign_key: true - t.belongs_to :tag, null: false, foreign_key: true - end - end -end diff --git a/db/migrate/20231115092055_rename_tasks_tags_to_tags_tasks.rb b/db/migrate/20231115092055_rename_tasks_tags_to_tags_tasks.rb deleted file mode 100644 index 4749cd2..0000000 --- a/db/migrate/20231115092055_rename_tasks_tags_to_tags_tasks.rb +++ /dev/null @@ -1,5 +0,0 @@ -class RenameTasksTagsToTagsTasks < ActiveRecord::Migration[7.1] - def change - rename_table :tasks_tags, :tags_tasks - end -end diff --git a/db/migrate/20231116112552_create_notes.rb b/db/migrate/20231116112552_create_notes.rb deleted file mode 100644 index c127ea6..0000000 --- a/db/migrate/20231116112552_create_notes.rb +++ /dev/null @@ -1,10 +0,0 @@ -class CreateNotes < ActiveRecord::Migration[7.1] - def change - create_table :notes do |t| - t.text :content - t.references :user, null: false, foreign_key: { on_delete: :cascade } - - t.timestamps - end - end -end diff --git a/db/migrate/20231116120633_create_join_table_notes_tags.rb b/db/migrate/20231116120633_create_join_table_notes_tags.rb deleted file mode 100644 index 2c605ca..0000000 --- a/db/migrate/20231116120633_create_join_table_notes_tags.rb +++ /dev/null @@ -1,8 +0,0 @@ -class CreateJoinTableNotesTags < ActiveRecord::Migration[7.1] - def change - create_join_table :notes, :tags do |t| - t.index :note_id - t.index :tag_id - end - end -end diff --git a/db/migrate/20231117170940_add_title_to_notes.rb b/db/migrate/20231117170940_add_title_to_notes.rb deleted file mode 100644 index 3bae3a8..0000000 --- a/db/migrate/20231117170940_add_title_to_notes.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddTitleToNotes < ActiveRecord::Migration[7.1] - def change - add_column :notes, :title, :string - end -end diff --git a/db/migrate/20231117174412_add_project_to_notes.rb b/db/migrate/20231117174412_add_project_to_notes.rb deleted file mode 100644 index afc74d3..0000000 --- a/db/migrate/20231117174412_add_project_to_notes.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddProjectToNotes < ActiveRecord::Migration[7.1] - def change - add_reference :notes, :project, foreign_key: true - end -end diff --git a/db/migrate/20231127092131_change_priority_in_tasks.rb b/db/migrate/20231127092131_change_priority_in_tasks.rb deleted file mode 100644 index 4b8b044..0000000 --- a/db/migrate/20231127092131_change_priority_in_tasks.rb +++ /dev/null @@ -1,33 +0,0 @@ -class ChangePriorityInTasks < ActiveRecord::Migration[7.1] - def up - add_column :tasks, :new_priority, :integer - - execute <<-SQL.squish - UPDATE tasks SET new_priority = CASE - WHEN priority = 'Low' THEN 0 - WHEN priority = 'Medium' THEN 1 - WHEN priority = 'High' THEN 2 - ELSE 0 - END - SQL - - remove_column :tasks, :priority - rename_column :tasks, :new_priority, :priority - end - - def down - add_column :tasks, :old_priority, :string - - execute <<-SQL.squish - UPDATE tasks SET old_priority = CASE - WHEN priority = 0 THEN 'Low' - WHEN priority = 1 THEN 'Medium' - WHEN priority = 2 THEN 'High' - ELSE 'Low' - END - SQL - - remove_column :tasks, :priority - rename_column :tasks, :old_priority, :priority - end -end diff --git a/db/migrate/20231127094906_add_note_and_status_to_tasks.rb b/db/migrate/20231127094906_add_note_and_status_to_tasks.rb deleted file mode 100644 index 3f94ba8..0000000 --- a/db/migrate/20231127094906_add_note_and_status_to_tasks.rb +++ /dev/null @@ -1,27 +0,0 @@ -class AddNoteAndStatusToTasks < ActiveRecord::Migration[7.1] - def up - add_column :tasks, :note, :text - add_column :tasks, :status, :integer, default: 0 - - execute <<-SQL.squish - UPDATE tasks SET status = CASE - WHEN completed = 't' THEN 2 - ELSE 0 - END - SQL - - remove_column :tasks, :completed - end - - def down - add_column :tasks, :completed, :boolean, default: false - - execute <<-SQL.squish - UPDATE tasks SET completed = 't' - WHERE status = 2 - SQL - - remove_column :tasks, :status - remove_column :tasks, :note - end -end diff --git a/db/migrate/20240326093339_add_active_to_projects.rb b/db/migrate/20240326093339_add_active_to_projects.rb deleted file mode 100644 index ac54d4b..0000000 --- a/db/migrate/20240326093339_add_active_to_projects.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddActiveToProjects < ActiveRecord::Migration[7.1] - def change - add_column :projects, :active, :boolean, default: false - end -end diff --git a/db/migrate/20241006225631_add_pin_to_sidebar_to_projects.rb b/db/migrate/20241006225631_add_pin_to_sidebar_to_projects.rb deleted file mode 100644 index 43c8a6b..0000000 --- a/db/migrate/20241006225631_add_pin_to_sidebar_to_projects.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddPinToSidebarToProjects < ActiveRecord::Migration[7.1] - def change - add_column :projects, :pin_to_sidebar, :boolean, default: false - end -end diff --git a/db/migrate/20241007143928_add_profile_fields_to_users.rb b/db/migrate/20241007143928_add_profile_fields_to_users.rb deleted file mode 100644 index 5970356..0000000 --- a/db/migrate/20241007143928_add_profile_fields_to_users.rb +++ /dev/null @@ -1,8 +0,0 @@ -class AddProfileFieldsToUsers < ActiveRecord::Migration[7.1] - def change - add_column :users, :appearance, :string, default: 'light', null: false - add_column :users, :language, :string, default: 'en', null: false - add_column :users, :timezone, :string, default: 'UTC', null: false - add_column :users, :avatar_image, :string - end -end diff --git a/db/migrate/20241016105827_create_description_for_area.rb b/db/migrate/20241016105827_create_description_for_area.rb deleted file mode 100644 index 444d68f..0000000 --- a/db/migrate/20241016105827_create_description_for_area.rb +++ /dev/null @@ -1,5 +0,0 @@ -class CreateDescriptionForArea < ActiveRecord::Migration[7.1] - def change - add_column :areas, :description, :string - end -end diff --git a/db/migrate/20241121113756_create_projects_tags.rb b/db/migrate/20241121113756_create_projects_tags.rb deleted file mode 100644 index 7334df7..0000000 --- a/db/migrate/20241121113756_create_projects_tags.rb +++ /dev/null @@ -1,14 +0,0 @@ -class CreateProjectsTags < ActiveRecord::Migration[7.1] - def change - create_table :projects_tags, id: false do |t| - t.integer :project_id, null: false - t.integer :tag_id, null: false - end - - add_index :projects_tags, :project_id - add_index :projects_tags, :tag_id - - add_foreign_key :projects_tags, :projects - add_foreign_key :projects_tags, :tags - end -end diff --git a/db/migrate/20241126095028_add_priority_to_projects.rb b/db/migrate/20241126095028_add_priority_to_projects.rb deleted file mode 100644 index 74b8ac9..0000000 --- a/db/migrate/20241126095028_add_priority_to_projects.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddPriorityToProjects < ActiveRecord::Migration[7.1] - def change - add_column :projects, :priority, :integer - end -end diff --git a/db/migrate/20250224162915_add_due_date_at_to_projects.rb b/db/migrate/20250224162915_add_due_date_at_to_projects.rb deleted file mode 100644 index 34f47ac..0000000 --- a/db/migrate/20250224162915_add_due_date_at_to_projects.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddDueDateAtToProjects < ActiveRecord::Migration[7.1] - def change - add_column :projects, :due_date_at, :datetime - end -end diff --git a/db/migrate/20250414134722_create_inbox_items.rb b/db/migrate/20250414134722_create_inbox_items.rb deleted file mode 100644 index 009477b..0000000 --- a/db/migrate/20250414134722_create_inbox_items.rb +++ /dev/null @@ -1,11 +0,0 @@ -class CreateInboxItems < ActiveRecord::Migration[7.1] - def change - create_table :inbox_items do |t| - t.string :content, null: false - t.references :user, null: false, foreign_key: true - t.string :status, default: 'added' - t.string :source, default: 'tududi' - t.timestamps - end - end -end diff --git a/db/migrate/20250414150330_add_telegram_token_to_users.rb b/db/migrate/20250414150330_add_telegram_token_to_users.rb deleted file mode 100644 index e2f930c..0000000 --- a/db/migrate/20250414150330_add_telegram_token_to_users.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddTelegramTokenToUsers < ActiveRecord::Migration[7.1] - def change - add_column :users, :telegram_bot_token, :string - add_column :users, :telegram_chat_id, :string - end -end diff --git a/db/migrate/20250416231240_add_task_summary_to_users.rb b/db/migrate/20250416231240_add_task_summary_to_users.rb deleted file mode 100644 index 798375b..0000000 --- a/db/migrate/20250416231240_add_task_summary_to_users.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AddTaskSummaryToUsers < ActiveRecord::Migration[7.1] - def change - add_column :users, :task_summary_enabled, :boolean, default: false - add_column :users, :task_summary_frequency, :string, default: 'daily' - end -end - diff --git a/db/migrate/20250416235420_add_task_summary_run_tracking_to_users.rb b/db/migrate/20250416235420_add_task_summary_run_tracking_to_users.rb deleted file mode 100644 index 2cc9878..0000000 --- a/db/migrate/20250416235420_add_task_summary_run_tracking_to_users.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AddTaskSummaryRunTrackingToUsers < ActiveRecord::Migration[7.1] - def change - add_column :users, :task_summary_last_run, :datetime - add_column :users, :task_summary_next_run, :datetime - end -end - diff --git a/db/schema.rb b/db/schema.rb deleted file mode 100644 index a261c6d..0000000 --- a/db/schema.rb +++ /dev/null @@ -1,141 +0,0 @@ -# This file is auto-generated from the current state of the database. Instead -# of editing this file, please use the migrations feature of Active Record to -# incrementally modify your database, and then regenerate this schema definition. -# -# This file is the source Rails uses to define your schema when running `bin/rails -# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to -# be faster and is potentially less error prone than running all of your -# migrations from scratch. Old migrations may fail to apply correctly if those -# migrations use external dependencies or application code. -# -# It's strongly recommended that you check this file into your version control system. - -ActiveRecord::Schema[7.1].define(version: 2025_04_16_235420) do - create_table "areas", force: :cascade do |t| - t.string "name" - t.integer "user_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "description" - t.index ["user_id"], name: "index_areas_on_user_id" - end - - create_table "inbox_items", force: :cascade do |t| - t.string "content", null: false - t.integer "user_id", null: false - t.string "status", default: "added" - t.string "source", default: "tududi" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["user_id"], name: "index_inbox_items_on_user_id" - end - - create_table "notes", force: :cascade do |t| - t.text "content" - t.integer "user_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "title" - t.integer "project_id" - t.index ["project_id"], name: "index_notes_on_project_id" - t.index ["user_id"], name: "index_notes_on_user_id" - end - - create_table "notes_tags", id: false, force: :cascade do |t| - t.integer "note_id", null: false - t.integer "tag_id", null: false - t.index ["note_id"], name: "index_notes_tags_on_note_id" - t.index ["tag_id"], name: "index_notes_tags_on_tag_id" - end - - create_table "projects", force: :cascade do |t| - t.string "name" - t.integer "user_id", null: false - t.integer "area_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.text "description" - t.boolean "active", default: false - t.boolean "pin_to_sidebar", default: false - t.integer "priority" - t.datetime "due_date_at" - t.index ["area_id"], name: "index_projects_on_area_id" - t.index ["user_id"], name: "index_projects_on_user_id" - end - - create_table "projects_tags", id: false, force: :cascade do |t| - t.integer "project_id", null: false - t.integer "tag_id", null: false - t.index ["project_id"], name: "index_projects_tags_on_project_id" - t.index ["tag_id"], name: "index_projects_tags_on_tag_id" - end - - create_table "tags", force: :cascade do |t| - t.string "name" - t.integer "user_id", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["user_id"], name: "index_tags_on_user_id" - end - - create_table "tags_tasks", id: false, force: :cascade do |t| - t.integer "task_id", null: false - t.integer "tag_id", null: false - t.index ["tag_id"], name: "index_tags_tasks_on_tag_id" - t.index ["task_id"], name: "index_tags_tasks_on_task_id" - end - - create_table "tasks", force: :cascade do |t| - t.string "name" - t.datetime "due_date" - t.integer "user_id", null: false - t.integer "project_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.boolean "today", default: false - t.text "description" - t.integer "priority" - t.text "note" - t.integer "status", default: 0 - t.string "recurrence_type", default: "none" - t.integer "recurrence_interval" - t.datetime "recurrence_end_date" - t.datetime "last_generated_date" - t.index ["last_generated_date"], name: "index_tasks_on_last_generated_date" - t.index ["project_id"], name: "index_tasks_on_project_id" - t.index ["recurrence_type"], name: "index_tasks_on_recurrence_type" - t.index ["user_id"], name: "index_tasks_on_user_id" - end - - create_table "users", force: :cascade do |t| - t.string "name" - t.string "email" - t.string "password_digest" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "appearance", default: "light", null: false - t.string "language", default: "en", null: false - t.string "timezone", default: "UTC", null: false - t.string "avatar_image" - t.string "telegram_bot_token" - t.string "telegram_chat_id" - t.boolean "task_summary_enabled", default: false - t.string "task_summary_frequency", default: "daily" - t.datetime "task_summary_last_run" - t.datetime "task_summary_next_run" - end - - add_foreign_key "areas", "users" - add_foreign_key "inbox_items", "users" - add_foreign_key "notes", "projects" - add_foreign_key "notes", "users", on_delete: :cascade - add_foreign_key "projects", "areas", on_delete: :cascade - add_foreign_key "projects", "users" - add_foreign_key "projects_tags", "projects" - add_foreign_key "projects_tags", "tags" - add_foreign_key "tags", "users", on_delete: :cascade - add_foreign_key "tags_tasks", "tags" - add_foreign_key "tags_tasks", "tasks" - add_foreign_key "tasks", "projects", on_delete: :cascade - add_foreign_key "tasks", "users" -end diff --git a/db/seeds.rb b/db/seeds.rb deleted file mode 100644 index 96188ef..0000000 --- a/db/seeds.rb +++ /dev/null @@ -1,39 +0,0 @@ -require 'faker' - -user = User.create(email: 'myemail@somewhere.com', password: 'awes0meHax0Rp4ssword') -user_id = user.id - -4.times do - Area.create(name: Faker::Space.galaxy, user_id: user_id) -end - -areas = Area.where(user_id: user_id) - -total_projects = 10 -projects_per_area = total_projects / areas.count -areas.each do |area| - projects_per_area.times do - Project.create( - name: Faker::App.name, - description: Faker::Lorem.sentence(word_count: 10), - user_id: user_id, - area_id: area.id - ) - end -end - -projects = Project.where(user_id: user_id) - -projects.each do |project| - 8.times do - Task.create( - name: Faker::Lorem.sentence(word_count: 3), - priority: %w[Low Medium High].sample, - due_date: [Date.today, Date.today + rand(1..30), nil].sample, - description: Faker::Lorem.sentence(word_count: 15), - status: [0, 1, 2].sample, - user_id: user_id, - project_id: project.id - ) - end -end diff --git a/dist/frontend_components_Tasks_tsx.bcee0af8633c28243d32.js b/dist/frontend_components_Tasks_tsx.bcee0af8633c28243d32.js deleted file mode 100644 index c0218be..0000000 --- a/dist/frontend_components_Tasks_tsx.bcee0af8633c28243d32.js +++ /dev/null @@ -1,92 +0,0 @@ -"use strict"; -/* - * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). - * This devtool is neither made for production nor for readable output files. - * It uses "eval()" calls to create a separate source file in the browser devtools. - * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) - * or disable the default devtool with "devtool: false". - * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). - */ -(self["webpackChunktududi"] = self["webpackChunktududi"] || []).push([["frontend_components_Tasks_tsx"],{ - -/***/ "./frontend/components/Task/getDescription.ts": -/*!****************************************************!*\ - !*** ./frontend/components/Task/getDescription.ts ***! - \****************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ getDescription: () => (/* binding */ getDescription)\n/* harmony export */ });\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar getDescription = function getDescription(query, projects, t) {\n try {\n // Default descriptions as fallbacks in case translation function fails\n var defaultDescriptions = {\n project: \"Project tasks\",\n today: \"Tasks due today or scheduled for immediate attention\",\n inbox: \"Uncategorized tasks without project or due date\",\n next: \"Tasks that are actionable in the near future\",\n upcoming: \"Tasks scheduled for the upcoming week\",\n someday: \"Tasks without urgency or specific due date\",\n completed: \"Tasks you've completed\",\n allTasks: \"All tasks from different projects and priorities\"\n };\n\n // Check for project_id first\n var projectId = query.get('project_id');\n if (projectId) {\n try {\n var project = projects.find(function (p) {\n var _p$id;\n return ((_p$id = p.id) === null || _p$id === void 0 ? void 0 : _p$id.toString()) === projectId;\n });\n if (project) {\n return t(\"taskViews.project.withName\", {\n projectName: project.name\n });\n } else {\n return t(\"taskViews.project.noName\");\n }\n } catch (e) {\n console.error(\"Translation error for project description:\", e);\n // Fallback with project name if available\n var _project = projects.find(function (p) {\n var _p$id2;\n return ((_p$id2 = p.id) === null || _p$id2 === void 0 ? void 0 : _p$id2.toString()) === projectId;\n });\n return _project ? \"Tasks for project: \".concat(_project.name) : defaultDescriptions.project;\n }\n }\n\n // Then check for type and status parameters\n try {\n if (query.get('type') === 'today') {\n return t(\"taskViews.today\");\n }\n if (query.get('type') === 'inbox') {\n return t(\"taskViews.inbox\");\n }\n if (query.get('type') === 'next') {\n return t(\"taskViews.next\");\n }\n if (query.get('type') === 'upcoming') {\n return t(\"taskViews.upcoming\");\n }\n if (query.get('type') === 'someday') {\n return t(\"taskViews.someday\");\n }\n if (query.get('status') === 'done') {\n return t(\"taskViews.completed\");\n }\n return t(\"taskViews.allTasks\");\n } catch (e) {\n console.error(\"Translation error for task view description:\", e);\n\n // Return appropriate fallback based on type or status\n if (query.get('type') === 'today') return defaultDescriptions.today;\n if (query.get('type') === 'inbox') return defaultDescriptions.inbox;\n if (query.get('type') === 'next') return defaultDescriptions.next;\n if (query.get('type') === 'upcoming') return defaultDescriptions.upcoming;\n if (query.get('type') === 'someday') return defaultDescriptions.someday;\n if (query.get('status') === 'done') return defaultDescriptions.completed;\n return defaultDescriptions.allTasks;\n }\n } catch (error) {\n console.error(\"Error in getDescription:\", error);\n return \"Tasks overview\";\n }\n};\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Task/getDescription.ts?"); - -/***/ }), - -/***/ "./frontend/components/Task/getTitleAndIcon.ts": -/*!*****************************************************!*\ - !*** ./frontend/components/Task/getTitleAndIcon.ts ***! - \*****************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ getTitleAndIcon: () => (/* binding */ getTitleAndIcon)\n/* harmony export */ });\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/FolderIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/CalendarIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/InboxIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/ArrowRightIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/ClockIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/MoonIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/CheckCircleIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/Bars4Icon.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\n\nvar getTitleAndIcon = function getTitleAndIcon(query, projects, t) {\n try {\n // Default titles as fallbacks in case translation function fails\n var defaultTitles = {\n project: 'Project',\n today: 'Today',\n inbox: 'Inbox',\n next: 'Next Actions',\n upcoming: 'Upcoming',\n someday: 'Someday',\n completed: 'Completed',\n allTasks: 'All Tasks'\n };\n var projectId = query.get('project_id');\n if (projectId) {\n var project = projects.find(function (p) {\n var _p$id;\n return ((_p$id = p.id) === null || _p$id === void 0 ? void 0 : _p$id.toString()) === projectId;\n });\n return {\n title: project ? project.name : t('sidebar.projects'),\n icon: _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_0__[\"default\"]\n };\n }\n try {\n if (query.get('type') === 'today') {\n return {\n title: t('tasks.today'),\n icon: _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_1__[\"default\"]\n };\n }\n if (query.get('type') === 'inbox') {\n return {\n title: t('sidebar.inbox'),\n icon: _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__[\"default\"]\n };\n }\n if (query.get('type') === 'next') {\n return {\n title: t('sidebar.nextActions'),\n icon: _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__[\"default\"]\n };\n }\n if (query.get('type') === 'upcoming') {\n return {\n title: t('sidebar.upcoming'),\n icon: _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_4__[\"default\"]\n };\n }\n if (query.get('type') === 'someday') {\n return {\n title: t('taskViews.someday') || defaultTitles.someday,\n icon: _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_5__[\"default\"]\n };\n }\n if (query.get('status') === 'done') {\n return {\n title: t('sidebar.completed'),\n icon: _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_6__[\"default\"]\n };\n }\n return {\n title: t('sidebar.allTasks'),\n icon: _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_7__[\"default\"]\n };\n } catch (e) {\n console.error(\"Translation error for task view title:\", e);\n\n // Return appropriate fallback based on type or status\n if (query.get('type') === 'today') return {\n title: defaultTitles.today,\n icon: _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_1__[\"default\"]\n };\n if (query.get('type') === 'inbox') return {\n title: defaultTitles.inbox,\n icon: _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__[\"default\"]\n };\n if (query.get('type') === 'next') return {\n title: defaultTitles.next,\n icon: _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__[\"default\"]\n };\n if (query.get('type') === 'upcoming') return {\n title: defaultTitles.upcoming,\n icon: _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_4__[\"default\"]\n };\n if (query.get('type') === 'someday') return {\n title: defaultTitles.someday,\n icon: _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_5__[\"default\"]\n };\n if (query.get('status') === 'done') return {\n title: defaultTitles.completed,\n icon: _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_6__[\"default\"]\n };\n return {\n title: defaultTitles.allTasks,\n icon: _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_7__[\"default\"]\n };\n }\n } catch (error) {\n console.error(\"Error in getTitleAndIcon:\", error);\n return {\n title: \"Tasks\",\n icon: _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_7__[\"default\"]\n };\n }\n};\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Task/getTitleAndIcon.ts?"); - -/***/ }), - -/***/ "./frontend/components/Tasks.tsx": -/*!***************************************!*\ - !*** ./frontend/components/Tasks.tsx ***! - \***************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router/dist/index.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* harmony import */ var _Task_TaskList__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Task/TaskList */ \"./frontend/components/Task/TaskList.tsx\");\n/* harmony import */ var _Task_NewTask__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Task/NewTask */ \"./frontend/components/Task/NewTask.tsx\");\n/* harmony import */ var _Task_getTitleAndIcon__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Task/getTitleAndIcon */ \"./frontend/components/Task/getTitleAndIcon.ts\");\n/* harmony import */ var _Task_getDescription__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Task/getDescription */ \"./frontend/components/Task/getDescription.ts\");\n/* harmony import */ var _utils_tasksService__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../utils/tasksService */ \"./frontend/utils/tasksService.ts\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/TagIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/XMarkIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/ChevronDoubleDownIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/ChevronDownIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/MagnifyingGlassIcon.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\n\n\n\n\nvar capitalize = function capitalize(str) {\n return str.charAt(0).toUpperCase() + str.slice(1);\n};\n\n// Helper function to get search placeholder by language\nvar getSearchPlaceholder = function getSearchPlaceholder(language) {\n var placeholders = {\n en: 'Search tasks...',\n el: 'Αναζήτηση εργασιών...',\n es: 'Buscar tareas...',\n de: 'Aufgaben suchen...',\n jp: 'タスクを検索...',\n ua: 'Пошук завдань...'\n };\n return placeholders[language] || 'Search tasks...';\n};\nvar Tasks = function Tasks() {\n _s();\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t,\n i18n = _useTranslation.i18n;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)([]),\n _useState2 = _slicedToArray(_useState, 2),\n tasks = _useState2[0],\n setTasks = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)([]),\n _useState4 = _slicedToArray(_useState3, 2),\n projects = _useState4[0],\n setProjects = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(true),\n _useState6 = _slicedToArray(_useState5, 2),\n loading = _useState6[0],\n setLoading = _useState6[1];\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState8 = _slicedToArray(_useState7, 2),\n error = _useState8[0],\n setError = _useState8[1];\n var _useState9 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState10 = _slicedToArray(_useState9, 2),\n dropdownOpen = _useState10[0],\n setDropdownOpen = _useState10[1];\n var _useState11 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(\"due_date:asc\"),\n _useState12 = _slicedToArray(_useState11, 2),\n orderBy = _useState12[0],\n setOrderBy = _useState12[1];\n var _useState13 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(\"\"),\n _useState14 = _slicedToArray(_useState13, 2),\n taskSearchQuery = _useState14[0],\n setTaskSearchQuery = _useState14[1];\n var dropdownRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n var location = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_7__.useLocation)();\n var navigate = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_7__.useNavigate)();\n var query = new URLSearchParams(location.search);\n var _ref = location.state || {},\n stateTitle = _ref.title,\n stateIcon = _ref.icon;\n var _ref2 = stateTitle && stateIcon ? {\n title: stateTitle,\n icon: stateIcon\n } : (0,_Task_getTitleAndIcon__WEBPACK_IMPORTED_MODULE_4__.getTitleAndIcon)(query, projects, t),\n title = _ref2.title,\n icon = _ref2.icon;\n var IconComponent = typeof icon === \"string\" ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(icon) : icon;\n var tag = query.get(\"tag\");\n var status = query.get(\"status\");\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var savedOrderBy = localStorage.getItem(\"order_by\") || \"due_date:asc\";\n setOrderBy(savedOrderBy);\n var params = new URLSearchParams(location.search);\n if (!params.get(\"order_by\")) {\n params.set(\"order_by\", savedOrderBy);\n navigate({\n pathname: location.pathname,\n search: \"?\".concat(params.toString())\n }, {\n replace: true\n });\n }\n }, [location.pathname]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleClickOutside = function handleClickOutside(event) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {\n setDropdownOpen(false);\n }\n };\n if (dropdownOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n }\n return function () {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, [dropdownOpen]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var fetchData = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var tagId, _yield$Promise$all, _yield$Promise$all2, tasksResponse, projectsResponse, tasksData, projectsData;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n setLoading(true);\n setError(null);\n _context.prev = 2;\n tagId = query.get(\"tag\");\n _context.next = 6;\n return Promise.all([fetch(\"/api/tasks\".concat(location.search).concat(tagId ? \"&tag=\".concat(tagId) : \"\")), fetch(\"/api/projects\")]);\n case 6:\n _yield$Promise$all = _context.sent;\n _yield$Promise$all2 = _slicedToArray(_yield$Promise$all, 2);\n tasksResponse = _yield$Promise$all2[0];\n projectsResponse = _yield$Promise$all2[1];\n if (!tasksResponse.ok) {\n _context.next = 17;\n break;\n }\n _context.next = 13;\n return tasksResponse.json();\n case 13:\n tasksData = _context.sent;\n setTasks(tasksData.tasks || []);\n _context.next = 18;\n break;\n case 17:\n throw new Error(\"Failed to fetch tasks.\");\n case 18:\n if (!projectsResponse.ok) {\n _context.next = 25;\n break;\n }\n _context.next = 21;\n return projectsResponse.json();\n case 21:\n projectsData = _context.sent;\n setProjects((projectsData === null || projectsData === void 0 ? void 0 : projectsData.projects) || []);\n _context.next = 26;\n break;\n case 25:\n throw new Error(\"Failed to fetch projects.\");\n case 26:\n _context.next = 31;\n break;\n case 28:\n _context.prev = 28;\n _context.t0 = _context[\"catch\"](2);\n setError(_context.t0.message);\n case 31:\n _context.prev = 31;\n setLoading(false);\n return _context.finish(31);\n case 34:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[2, 28, 31, 34]]);\n }));\n return function fetchData() {\n return _ref3.apply(this, arguments);\n };\n }();\n fetchData();\n }, [location]);\n var handleRemoveTag = function handleRemoveTag() {\n var params = new URLSearchParams(location.search);\n params[\"delete\"](\"tag\");\n navigate({\n pathname: location.pathname,\n search: \"?\".concat(params.toString())\n });\n };\n var handleTaskCreate = /*#__PURE__*/function () {\n var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(taskData) {\n var newTask;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n _context2.prev = 0;\n _context2.next = 3;\n return (0,_utils_tasksService__WEBPACK_IMPORTED_MODULE_6__.createTask)(taskData);\n case 3:\n newTask = _context2.sent;\n // Add the new task optimistically to avoid race conditions\n setTasks(function (prevTasks) {\n return [newTask].concat(_toConsumableArray(prevTasks));\n });\n _context2.next = 12;\n break;\n case 7:\n _context2.prev = 7;\n _context2.t0 = _context2[\"catch\"](0);\n console.error(\"Error creating task:\", _context2.t0);\n setError(\"Error creating task.\");\n throw _context2.t0;\n case 12:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, null, [[0, 7]]);\n }));\n return function handleTaskCreate(_x) {\n return _ref4.apply(this, arguments);\n };\n }();\n var handleTaskUpdate = /*#__PURE__*/function () {\n var _ref5 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(updatedTask) {\n var response, errorData;\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n _context3.prev = 0;\n _context3.next = 3;\n return fetch(\"/api/task/\".concat(updatedTask.id), {\n method: \"PATCH\",\n headers: {\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(updatedTask)\n });\n case 3:\n response = _context3.sent;\n if (!response.ok) {\n _context3.next = 8;\n break;\n }\n setTasks(function (prevTasks) {\n return prevTasks.map(function (task) {\n return task.id === updatedTask.id ? updatedTask : task;\n });\n });\n _context3.next = 13;\n break;\n case 8:\n _context3.next = 10;\n return response.json();\n case 10:\n errorData = _context3.sent;\n console.error(\"Failed to update task:\", errorData.error);\n setError(\"Failed to update task.\");\n case 13:\n _context3.next = 19;\n break;\n case 15:\n _context3.prev = 15;\n _context3.t0 = _context3[\"catch\"](0);\n console.error(\"Error updating task:\", _context3.t0);\n setError(\"Error updating task.\");\n case 19:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3, null, [[0, 15]]);\n }));\n return function handleTaskUpdate(_x2) {\n return _ref5.apply(this, arguments);\n };\n }();\n var handleTaskDelete = /*#__PURE__*/function () {\n var _ref6 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4(taskId) {\n var response, errorData;\n return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n while (1) switch (_context4.prev = _context4.next) {\n case 0:\n _context4.prev = 0;\n _context4.next = 3;\n return fetch(\"/api/task/\".concat(taskId), {\n method: \"DELETE\"\n });\n case 3:\n response = _context4.sent;\n if (!response.ok) {\n _context4.next = 8;\n break;\n }\n setTasks(function (prevTasks) {\n return prevTasks.filter(function (task) {\n return task.id !== taskId;\n });\n });\n _context4.next = 13;\n break;\n case 8:\n _context4.next = 10;\n return response.json();\n case 10:\n errorData = _context4.sent;\n console.error(\"Failed to delete task:\", errorData.error);\n setError(\"Failed to delete task.\");\n case 13:\n _context4.next = 19;\n break;\n case 15:\n _context4.prev = 15;\n _context4.t0 = _context4[\"catch\"](0);\n console.error(\"Error deleting task:\", _context4.t0);\n setError(\"Error deleting task.\");\n case 19:\n case \"end\":\n return _context4.stop();\n }\n }, _callee4, null, [[0, 15]]);\n }));\n return function handleTaskDelete(_x3) {\n return _ref6.apply(this, arguments);\n };\n }();\n var handleSortChange = function handleSortChange(order) {\n setOrderBy(order);\n localStorage.setItem(\"order_by\", order);\n var params = new URLSearchParams(location.search);\n params.set(\"order_by\", order);\n navigate({\n pathname: location.pathname,\n search: \"?\".concat(params.toString())\n }, {\n replace: true\n });\n setDropdownOpen(false);\n };\n var description = (0,_Task_getDescription__WEBPACK_IMPORTED_MODULE_5__.getDescription)(query, projects, t);\n var isNewTaskAllowed = function isNewTaskAllowed() {\n return status !== \"done\";\n };\n var filteredTasks = tasks.filter(function (task) {\n return task.name.toLowerCase().includes(taskSearchQuery.toLowerCase());\n });\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex justify-center px-4 lg:px-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-full max-w-5xl\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex flex-col sm:flex-row items-start sm:items-center justify-between mb-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center mb-2 sm:mb-0\"\n }, IconComponent && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(IconComponent, {\n className: \"h-6 w-6 mr-2\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h2\", {\n className: \"text-2xl font-light\"\n }, title), tag && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"ml-4 flex items-center space-x-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n className: \"flex items-center space-x-1 px-2 py-1 bg-gray-100 dark:bg-gray-700 rounded-lg cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-600\",\n onClick: handleRemoveTag\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n className: \"h-4 w-4 text-gray-500 dark:text-gray-300\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"text-xs text-gray-700 dark:text-gray-300\"\n }, capitalize(tag)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_9__[\"default\"], {\n className: \"h-4 w-4 text-gray-500 dark:text-gray-300 hover:text-red-500\"\n })))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"relative inline-block text-left\",\n ref: dropdownRef\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n className: \"inline-flex justify-center w-full rounded-md border border-gray-300 dark:border-gray-700 shadow-sm px-4 py-2 bg-white dark:bg-gray-800 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none\",\n id: \"menu-button\",\n \"aria-expanded\": dropdownOpen,\n \"aria-haspopup\": \"true\",\n onClick: function onClick() {\n return setDropdownOpen(!dropdownOpen);\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_10__[\"default\"], {\n className: \"h-5 w-5 text-gray-500 mr-2\"\n }), \" \", t(\"sort.\".concat(orderBy.split(\":\")[0]), capitalize(orderBy.split(\":\")[0].replace(\"_\", \" \"))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_11__[\"default\"], {\n className: \"h-5 w-5 ml-2 text-gray-500 dark:text-gray-300\"\n })), dropdownOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"origin-top-right absolute left-0 sm:right-0 sm:left-auto mt-2 w-full sm:w-56 max-w-full rounded-md shadow-lg bg-white dark:bg-gray-800 ring-1 ring-black ring-opacity-5 focus:outline-none z-10\",\n role: \"menu\",\n \"aria-orientation\": \"vertical\",\n \"aria-labelledby\": \"menu-button\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"py-1 max-h-60 overflow-y-auto\",\n role: \"none\"\n }, [\"due_date:asc\", \"name:asc\", \"priority:desc\", \"status:desc\", \"created_at:desc\"].map(function (order) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n key: order,\n onClick: function onClick() {\n return handleSortChange(order);\n },\n className: \"block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-600 w-full text-left\",\n role: \"menuitem\"\n }, t(\"sort.\".concat(order.split(\":\")[0]), capitalize(order.split(\":\")[0].replace(\"_\", \" \"))));\n }))))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"mb-6 text-sm text-gray-500 dark:text-gray-400\"\n }, description), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-md shadow-sm p-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_12__[\"default\"], {\n className: \"h-5 w-5 text-gray-500 dark:text-gray-400 mr-2\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"text\",\n placeholder: getSearchPlaceholder(i18n.language),\n value: taskSearchQuery,\n onChange: function onChange(e) {\n return setTaskSearchQuery(e.target.value);\n },\n className: \"w-full bg-transparent border-none focus:ring-0 focus:outline-none dark:text-white\"\n }))), loading ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", null, t('common.loading', 'Loading...')) : error ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-red-500\"\n }, error) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, isNewTaskAllowed() && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Task_NewTask__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n onTaskCreate: (/*#__PURE__*/function () {\n var _ref7 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee5(taskName) {\n return _regeneratorRuntime().wrap(function _callee5$(_context5) {\n while (1) switch (_context5.prev = _context5.next) {\n case 0:\n _context5.next = 2;\n return handleTaskCreate({\n name: taskName,\n status: \"not_started\"\n });\n case 2:\n return _context5.abrupt(\"return\", _context5.sent);\n case 3:\n case \"end\":\n return _context5.stop();\n }\n }, _callee5);\n }));\n return function (_x4) {\n return _ref7.apply(this, arguments);\n };\n }())\n }), filteredTasks.length > 0 ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Task_TaskList__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n tasks: filteredTasks,\n onTaskCreate: handleTaskCreate,\n onTaskUpdate: handleTaskUpdate,\n onTaskDelete: handleTaskDelete,\n projects: projects\n }) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-gray-500 text-center mt-4\"\n }, t('tasks.noTasksAvailable', 'Δεν υπάρχουν διαθέσιμες εργασίες.')))));\n};\n_s(Tasks, \"5Z8QLe2HIWOxwpw6vPkauZx5154=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation, react_router_dom__WEBPACK_IMPORTED_MODULE_7__.useLocation, react_router_dom__WEBPACK_IMPORTED_MODULE_7__.useNavigate];\n});\n_c = Tasks;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Tasks);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"Tasks\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Tasks.tsx?"); - -/***/ }), - -/***/ "./node_modules/@heroicons/react/24/outline/esm/ArrowRightIcon.js": -/*!************************************************************************!*\ - !*** ./node_modules/@heroicons/react/24/outline/esm/ArrowRightIcon.js ***! - \************************************************************************/ -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nfunction ArrowRightIcon({\n title,\n titleId,\n ...props\n}, svgRef) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"svg\", Object.assign({\n xmlns: \"http://www.w3.org/2000/svg\",\n fill: \"none\",\n viewBox: \"0 0 24 24\",\n strokeWidth: 1.5,\n stroke: \"currentColor\",\n \"aria-hidden\": \"true\",\n \"data-slot\": \"icon\",\n ref: svgRef,\n \"aria-labelledby\": titleId\n }, props), title ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"title\", {\n id: titleId\n }, title) : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"path\", {\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n d: \"M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3\"\n }));\n}\nconst ForwardRef = /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0__.forwardRef(ArrowRightIcon);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ForwardRef);\n\n//# sourceURL=webpack://tududi/./node_modules/@heroicons/react/24/outline/esm/ArrowRightIcon.js?"); - -/***/ }), - -/***/ "./node_modules/@heroicons/react/24/outline/esm/Bars4Icon.js": -/*!*******************************************************************!*\ - !*** ./node_modules/@heroicons/react/24/outline/esm/Bars4Icon.js ***! - \*******************************************************************/ -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nfunction Bars4Icon({\n title,\n titleId,\n ...props\n}, svgRef) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"svg\", Object.assign({\n xmlns: \"http://www.w3.org/2000/svg\",\n fill: \"none\",\n viewBox: \"0 0 24 24\",\n strokeWidth: 1.5,\n stroke: \"currentColor\",\n \"aria-hidden\": \"true\",\n \"data-slot\": \"icon\",\n ref: svgRef,\n \"aria-labelledby\": titleId\n }, props), title ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"title\", {\n id: titleId\n }, title) : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"path\", {\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n d: \"M3.75 5.25h16.5m-16.5 4.5h16.5m-16.5 4.5h16.5m-16.5 4.5h16.5\"\n }));\n}\nconst ForwardRef = /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0__.forwardRef(Bars4Icon);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ForwardRef);\n\n//# sourceURL=webpack://tududi/./node_modules/@heroicons/react/24/outline/esm/Bars4Icon.js?"); - -/***/ }), - -/***/ "./node_modules/@heroicons/react/24/outline/esm/CalendarIcon.js": -/*!**********************************************************************!*\ - !*** ./node_modules/@heroicons/react/24/outline/esm/CalendarIcon.js ***! - \**********************************************************************/ -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nfunction CalendarIcon({\n title,\n titleId,\n ...props\n}, svgRef) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"svg\", Object.assign({\n xmlns: \"http://www.w3.org/2000/svg\",\n fill: \"none\",\n viewBox: \"0 0 24 24\",\n strokeWidth: 1.5,\n stroke: \"currentColor\",\n \"aria-hidden\": \"true\",\n \"data-slot\": \"icon\",\n ref: svgRef,\n \"aria-labelledby\": titleId\n }, props), title ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"title\", {\n id: titleId\n }, title) : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"path\", {\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n d: \"M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5\"\n }));\n}\nconst ForwardRef = /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0__.forwardRef(CalendarIcon);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ForwardRef);\n\n//# sourceURL=webpack://tududi/./node_modules/@heroicons/react/24/outline/esm/CalendarIcon.js?"); - -/***/ }), - -/***/ "./node_modules/@heroicons/react/24/solid/esm/ChevronDoubleDownIcon.js": -/*!*****************************************************************************!*\ - !*** ./node_modules/@heroicons/react/24/solid/esm/ChevronDoubleDownIcon.js ***! - \*****************************************************************************/ -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nfunction ChevronDoubleDownIcon({\n title,\n titleId,\n ...props\n}, svgRef) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"svg\", Object.assign({\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 24 24\",\n fill: \"currentColor\",\n \"aria-hidden\": \"true\",\n \"data-slot\": \"icon\",\n ref: svgRef,\n \"aria-labelledby\": titleId\n }, props), title ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"title\", {\n id: titleId\n }, title) : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"path\", {\n fillRule: \"evenodd\",\n d: \"M11.47 13.28a.75.75 0 0 0 1.06 0l7.5-7.5a.75.75 0 0 0-1.06-1.06L12 11.69 5.03 4.72a.75.75 0 0 0-1.06 1.06l7.5 7.5Z\",\n clipRule: \"evenodd\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"path\", {\n fillRule: \"evenodd\",\n d: \"M11.47 19.28a.75.75 0 0 0 1.06 0l7.5-7.5a.75.75 0 1 0-1.06-1.06L12 17.69l-6.97-6.97a.75.75 0 0 0-1.06 1.06l7.5 7.5Z\",\n clipRule: \"evenodd\"\n }));\n}\nconst ForwardRef = /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0__.forwardRef(ChevronDoubleDownIcon);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ForwardRef);\n\n//# sourceURL=webpack://tududi/./node_modules/@heroicons/react/24/solid/esm/ChevronDoubleDownIcon.js?"); - -/***/ }), - -/***/ "./node_modules/@heroicons/react/24/solid/esm/ChevronDownIcon.js": -/*!***********************************************************************!*\ - !*** ./node_modules/@heroicons/react/24/solid/esm/ChevronDownIcon.js ***! - \***********************************************************************/ -/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { - -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nfunction ChevronDownIcon({\n title,\n titleId,\n ...props\n}, svgRef) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"svg\", Object.assign({\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 24 24\",\n fill: \"currentColor\",\n \"aria-hidden\": \"true\",\n \"data-slot\": \"icon\",\n ref: svgRef,\n \"aria-labelledby\": titleId\n }, props), title ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"title\", {\n id: titleId\n }, title) : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"path\", {\n fillRule: \"evenodd\",\n d: \"M12.53 16.28a.75.75 0 0 1-1.06 0l-7.5-7.5a.75.75 0 0 1 1.06-1.06L12 14.69l6.97-6.97a.75.75 0 1 1 1.06 1.06l-7.5 7.5Z\",\n clipRule: \"evenodd\"\n }));\n}\nconst ForwardRef = /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0__.forwardRef(ChevronDownIcon);\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ForwardRef);\n\n//# sourceURL=webpack://tududi/./node_modules/@heroicons/react/24/solid/esm/ChevronDownIcon.js?"); - -/***/ }) - -}]); \ No newline at end of file diff --git a/dist/index.html b/dist/index.html deleted file mode 100644 index 85b2881..0000000 --- a/dist/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - Tududi - - -
- - \ No newline at end of file diff --git a/dist/main.5904574f25ca7c8b87ba.js b/dist/main.5904574f25ca7c8b87ba.js deleted file mode 100644 index b1e143c..0000000 --- a/dist/main.5904574f25ca7c8b87ba.js +++ /dev/null @@ -1,5392 +0,0 @@ -/* - * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). - * This devtool is neither made for production nor for readable output files. - * It uses "eval()" calls to create a separate source file in the browser devtools. - * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) - * or disable the default devtool with "devtool: false". - * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). - */ -/******/ (() => { // webpackBootstrap -/******/ var __webpack_modules__ = ({ - -/***/ "./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js": -/*!***************************************************************************************!*\ - !*** ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js ***! - \***************************************************************************************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -eval("/* global __webpack_require__ */\nvar Refresh = __webpack_require__(/*! react-refresh/runtime */ \"./node_modules/react-refresh/runtime.js\");\n\n/**\n * Extracts exports from a webpack module object.\n * @param {string} moduleId A Webpack module ID.\n * @returns {*} An exports object from the module.\n */\nfunction getModuleExports(moduleId) {\n if (typeof moduleId === 'undefined') {\n // `moduleId` is unavailable, which indicates that this module is not in the cache,\n // which means we won't be able to capture any exports,\n // and thus they cannot be refreshed safely.\n // These are likely runtime or dynamically generated modules.\n return {};\n }\n\n var maybeModule = __webpack_require__.c[moduleId];\n if (typeof maybeModule === 'undefined') {\n // `moduleId` is available but the module in cache is unavailable,\n // which indicates the module is somehow corrupted (e.g. broken Webpacak `module` globals).\n // We will warn the user (as this is likely a mistake) and assume they cannot be refreshed.\n console.warn('[React Refresh] Failed to get exports for module: ' + moduleId + '.');\n return {};\n }\n\n var exportsOrPromise = maybeModule.exports;\n if (typeof Promise !== 'undefined' && exportsOrPromise instanceof Promise) {\n return exportsOrPromise.then(function (exports) {\n return exports;\n });\n }\n return exportsOrPromise;\n}\n\n/**\n * Calculates the signature of a React refresh boundary.\n * If this signature changes, it's unsafe to accept the boundary.\n *\n * This implementation is based on the one in [Metro](https://github.com/facebook/metro/blob/907d6af22ac6ebe58572be418e9253a90665ecbd/packages/metro/src/lib/polyfills/require.js#L795-L816).\n * @param {*} moduleExports A Webpack module exports object.\n * @returns {string[]} A React refresh boundary signature array.\n */\nfunction getReactRefreshBoundarySignature(moduleExports) {\n var signature = [];\n signature.push(Refresh.getFamilyByType(moduleExports));\n\n if (moduleExports == null || typeof moduleExports !== 'object') {\n // Exit if we can't iterate over exports.\n return signature;\n }\n\n for (var key in moduleExports) {\n if (key === '__esModule') {\n continue;\n }\n\n signature.push(key);\n signature.push(Refresh.getFamilyByType(moduleExports[key]));\n }\n\n return signature;\n}\n\n/**\n * Creates a data object to be retained across refreshes.\n * This object should not transtively reference previous exports,\n * which can form infinite chain of objects across refreshes, which can pressure RAM.\n *\n * @param {*} moduleExports A Webpack module exports object.\n * @returns {*} A React refresh boundary signature array.\n */\nfunction getWebpackHotData(moduleExports) {\n return {\n signature: getReactRefreshBoundarySignature(moduleExports),\n isReactRefreshBoundary: isReactRefreshBoundary(moduleExports),\n };\n}\n\n/**\n * Creates a helper that performs a delayed React refresh.\n * @returns {function(function(): void): void} A debounced React refresh function.\n */\nfunction createDebounceUpdate() {\n /**\n * A cached setTimeout handler.\n * @type {number | undefined}\n */\n var refreshTimeout;\n\n /**\n * Performs react refresh on a delay and clears the error overlay.\n * @param {function(): void} callback\n * @returns {void}\n */\n function enqueueUpdate(callback) {\n if (typeof refreshTimeout === 'undefined') {\n refreshTimeout = setTimeout(function () {\n refreshTimeout = undefined;\n Refresh.performReactRefresh();\n callback();\n }, 30);\n }\n }\n\n return enqueueUpdate;\n}\n\n/**\n * Checks if all exports are likely a React component.\n *\n * This implementation is based on the one in [Metro](https://github.com/facebook/metro/blob/febdba2383113c88296c61e28e4ef6a7f4939fda/packages/metro/src/lib/polyfills/require.js#L748-L774).\n * @param {*} moduleExports A Webpack module exports object.\n * @returns {boolean} Whether the exports are React component like.\n */\nfunction isReactRefreshBoundary(moduleExports) {\n if (Refresh.isLikelyComponentType(moduleExports)) {\n return true;\n }\n if (moduleExports === undefined || moduleExports === null || typeof moduleExports !== 'object') {\n // Exit if we can't iterate over exports.\n return false;\n }\n\n var hasExports = false;\n var areAllExportsComponents = true;\n for (var key in moduleExports) {\n hasExports = true;\n\n // This is the ES Module indicator flag\n if (key === '__esModule') {\n continue;\n }\n\n // We can (and have to) safely execute getters here,\n // as Webpack manually assigns harmony exports to getters,\n // without any side-effects attached.\n // Ref: https://github.com/webpack/webpack/blob/b93048643fe74de2a6931755911da1212df55897/lib/MainTemplate.js#L281\n var exportValue = moduleExports[key];\n if (!Refresh.isLikelyComponentType(exportValue)) {\n areAllExportsComponents = false;\n }\n }\n\n return hasExports && areAllExportsComponents;\n}\n\n/**\n * Checks if exports are likely a React component and registers them.\n *\n * This implementation is based on the one in [Metro](https://github.com/facebook/metro/blob/febdba2383113c88296c61e28e4ef6a7f4939fda/packages/metro/src/lib/polyfills/require.js#L818-L835).\n * @param {*} moduleExports A Webpack module exports object.\n * @param {string} moduleId A Webpack module ID.\n * @returns {void}\n */\nfunction registerExportsForReactRefresh(moduleExports, moduleId) {\n if (Refresh.isLikelyComponentType(moduleExports)) {\n // Register module.exports if it is likely a component\n Refresh.register(moduleExports, moduleId + ' %exports%');\n }\n\n if (moduleExports === undefined || moduleExports === null || typeof moduleExports !== 'object') {\n // Exit if we can't iterate over the exports.\n return;\n }\n\n for (var key in moduleExports) {\n // Skip registering the ES Module indicator\n if (key === '__esModule') {\n continue;\n }\n\n var exportValue = moduleExports[key];\n if (Refresh.isLikelyComponentType(exportValue)) {\n var typeID = moduleId + ' %exports% ' + key;\n Refresh.register(exportValue, typeID);\n }\n }\n}\n\n/**\n * Compares previous and next module objects to check for mutated boundaries.\n *\n * This implementation is based on the one in [Metro](https://github.com/facebook/metro/blob/907d6af22ac6ebe58572be418e9253a90665ecbd/packages/metro/src/lib/polyfills/require.js#L776-L792).\n * @param {*} prevSignature The signature of the current Webpack module exports object.\n * @param {*} nextSignature The signature of the next Webpack module exports object.\n * @returns {boolean} Whether the React refresh boundary should be invalidated.\n */\nfunction shouldInvalidateReactRefreshBoundary(prevSignature, nextSignature) {\n if (prevSignature.length !== nextSignature.length) {\n return true;\n }\n\n for (var i = 0; i < nextSignature.length; i += 1) {\n if (prevSignature[i] !== nextSignature[i]) {\n return true;\n }\n }\n\n return false;\n}\n\nvar enqueueUpdate = createDebounceUpdate();\nfunction executeRuntime(moduleExports, moduleId, webpackHot, refreshOverlay, isTest) {\n registerExportsForReactRefresh(moduleExports, moduleId);\n\n if (webpackHot) {\n var isHotUpdate = !!webpackHot.data;\n var prevData;\n if (isHotUpdate) {\n prevData = webpackHot.data.prevData;\n }\n\n if (isReactRefreshBoundary(moduleExports)) {\n webpackHot.dispose(\n /**\n * A callback to performs a full refresh if React has unrecoverable errors,\n * and also caches the to-be-disposed module.\n * @param {*} data A hot module data object from Webpack HMR.\n * @returns {void}\n */\n function hotDisposeCallback(data) {\n // We have to mutate the data object to get data registered and cached\n data.prevData = getWebpackHotData(moduleExports);\n }\n );\n webpackHot.accept(\n /**\n * An error handler to allow self-recovering behaviours.\n * @param {Error} error An error occurred during evaluation of a module.\n * @returns {void}\n */\n function hotErrorHandler(error) {\n if (typeof refreshOverlay !== 'undefined' && refreshOverlay) {\n refreshOverlay.handleRuntimeError(error);\n }\n\n if (typeof isTest !== 'undefined' && isTest) {\n if (window.onHotAcceptError) {\n window.onHotAcceptError(error.message);\n }\n }\n\n __webpack_require__.c[moduleId].hot.accept(hotErrorHandler);\n }\n );\n\n if (isHotUpdate) {\n if (\n prevData &&\n prevData.isReactRefreshBoundary &&\n shouldInvalidateReactRefreshBoundary(\n prevData.signature,\n getReactRefreshBoundarySignature(moduleExports)\n )\n ) {\n webpackHot.invalidate();\n } else {\n enqueueUpdate(\n /**\n * A function to dismiss the error overlay after performing React refresh.\n * @returns {void}\n */\n function updateCallback() {\n if (typeof refreshOverlay !== 'undefined' && refreshOverlay) {\n refreshOverlay.clearRuntimeErrors();\n }\n }\n );\n }\n }\n } else {\n if (isHotUpdate && typeof prevData !== 'undefined') {\n webpackHot.invalidate();\n }\n }\n }\n}\n\nmodule.exports = Object.freeze({\n enqueueUpdate: enqueueUpdate,\n executeRuntime: executeRuntime,\n getModuleExports: getModuleExports,\n isReactRefreshBoundary: isReactRefreshBoundary,\n registerExportsForReactRefresh: registerExportsForReactRefresh,\n});\n\n\n//# sourceURL=webpack://tududi/./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js?"); - -/***/ }), - -/***/ "./node_modules/@remix-run/router/dist/router.js": -/*!*******************************************************!*\ - !*** ./node_modules/@remix-run/router/dist/router.js ***! - \*******************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ AbortedDeferredError: () => (/* binding */ AbortedDeferredError),\n/* harmony export */ Action: () => (/* binding */ Action),\n/* harmony export */ IDLE_BLOCKER: () => (/* binding */ IDLE_BLOCKER),\n/* harmony export */ IDLE_FETCHER: () => (/* binding */ IDLE_FETCHER),\n/* harmony export */ IDLE_NAVIGATION: () => (/* binding */ IDLE_NAVIGATION),\n/* harmony export */ UNSAFE_DEFERRED_SYMBOL: () => (/* binding */ UNSAFE_DEFERRED_SYMBOL),\n/* harmony export */ UNSAFE_DeferredData: () => (/* binding */ DeferredData),\n/* harmony export */ UNSAFE_ErrorResponseImpl: () => (/* binding */ ErrorResponseImpl),\n/* harmony export */ UNSAFE_convertRouteMatchToUiMatch: () => (/* binding */ convertRouteMatchToUiMatch),\n/* harmony export */ UNSAFE_convertRoutesToDataRoutes: () => (/* binding */ convertRoutesToDataRoutes),\n/* harmony export */ UNSAFE_decodePath: () => (/* binding */ decodePath),\n/* harmony export */ UNSAFE_getResolveToMatches: () => (/* binding */ getResolveToMatches),\n/* harmony export */ UNSAFE_invariant: () => (/* binding */ invariant),\n/* harmony export */ UNSAFE_warning: () => (/* binding */ warning),\n/* harmony export */ createBrowserHistory: () => (/* binding */ createBrowserHistory),\n/* harmony export */ createHashHistory: () => (/* binding */ createHashHistory),\n/* harmony export */ createMemoryHistory: () => (/* binding */ createMemoryHistory),\n/* harmony export */ createPath: () => (/* binding */ createPath),\n/* harmony export */ createRouter: () => (/* binding */ createRouter),\n/* harmony export */ createStaticHandler: () => (/* binding */ createStaticHandler),\n/* harmony export */ defer: () => (/* binding */ defer),\n/* harmony export */ generatePath: () => (/* binding */ generatePath),\n/* harmony export */ getStaticContextFromError: () => (/* binding */ getStaticContextFromError),\n/* harmony export */ getToPathname: () => (/* binding */ getToPathname),\n/* harmony export */ isDataWithResponseInit: () => (/* binding */ isDataWithResponseInit),\n/* harmony export */ isDeferredData: () => (/* binding */ isDeferredData),\n/* harmony export */ isRouteErrorResponse: () => (/* binding */ isRouteErrorResponse),\n/* harmony export */ joinPaths: () => (/* binding */ joinPaths),\n/* harmony export */ json: () => (/* binding */ json),\n/* harmony export */ matchPath: () => (/* binding */ matchPath),\n/* harmony export */ matchRoutes: () => (/* binding */ matchRoutes),\n/* harmony export */ normalizePathname: () => (/* binding */ normalizePathname),\n/* harmony export */ parsePath: () => (/* binding */ parsePath),\n/* harmony export */ redirect: () => (/* binding */ redirect),\n/* harmony export */ redirectDocument: () => (/* binding */ redirectDocument),\n/* harmony export */ replace: () => (/* binding */ replace),\n/* harmony export */ resolvePath: () => (/* binding */ resolvePath),\n/* harmony export */ resolveTo: () => (/* binding */ resolveTo),\n/* harmony export */ stripBasename: () => (/* binding */ stripBasename),\n/* harmony export */ unstable_data: () => (/* binding */ data)\n/* harmony export */ });\n/**\n * @remix-run/router v1.19.2\n *\n * Copyright (c) Remix Software Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE.md file in the root directory of this source tree.\n *\n * @license MIT\n */\nfunction _extends() {\n _extends = Object.assign ? Object.assign.bind() : function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n return target;\n };\n return _extends.apply(this, arguments);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Types and Constants\n////////////////////////////////////////////////////////////////////////////////\n/**\n * Actions represent the type of change to a location value.\n */\nvar Action;\n(function (Action) {\n /**\n * A POP indicates a change to an arbitrary index in the history stack, such\n * as a back or forward navigation. It does not describe the direction of the\n * navigation, only that the current index changed.\n *\n * Note: This is the default action for newly created history objects.\n */\n Action[\"Pop\"] = \"POP\";\n /**\n * A PUSH indicates a new entry being added to the history stack, such as when\n * a link is clicked and a new page loads. When this happens, all subsequent\n * entries in the stack are lost.\n */\n Action[\"Push\"] = \"PUSH\";\n /**\n * A REPLACE indicates the entry at the current index in the history stack\n * being replaced by a new one.\n */\n Action[\"Replace\"] = \"REPLACE\";\n})(Action || (Action = {}));\nconst PopStateEventType = \"popstate\";\n/**\n * Memory history stores the current location in memory. It is designed for use\n * in stateful non-browser environments like tests and React Native.\n */\nfunction createMemoryHistory(options) {\n if (options === void 0) {\n options = {};\n }\n let {\n initialEntries = [\"/\"],\n initialIndex,\n v5Compat = false\n } = options;\n let entries; // Declare so we can access from createMemoryLocation\n entries = initialEntries.map((entry, index) => createMemoryLocation(entry, typeof entry === \"string\" ? null : entry.state, index === 0 ? \"default\" : undefined));\n let index = clampIndex(initialIndex == null ? entries.length - 1 : initialIndex);\n let action = Action.Pop;\n let listener = null;\n function clampIndex(n) {\n return Math.min(Math.max(n, 0), entries.length - 1);\n }\n function getCurrentLocation() {\n return entries[index];\n }\n function createMemoryLocation(to, state, key) {\n if (state === void 0) {\n state = null;\n }\n let location = createLocation(entries ? getCurrentLocation().pathname : \"/\", to, state, key);\n warning(location.pathname.charAt(0) === \"/\", \"relative pathnames are not supported in memory history: \" + JSON.stringify(to));\n return location;\n }\n function createHref(to) {\n return typeof to === \"string\" ? to : createPath(to);\n }\n let history = {\n get index() {\n return index;\n },\n get action() {\n return action;\n },\n get location() {\n return getCurrentLocation();\n },\n createHref,\n createURL(to) {\n return new URL(createHref(to), \"http://localhost\");\n },\n encodeLocation(to) {\n let path = typeof to === \"string\" ? parsePath(to) : to;\n return {\n pathname: path.pathname || \"\",\n search: path.search || \"\",\n hash: path.hash || \"\"\n };\n },\n push(to, state) {\n action = Action.Push;\n let nextLocation = createMemoryLocation(to, state);\n index += 1;\n entries.splice(index, entries.length, nextLocation);\n if (v5Compat && listener) {\n listener({\n action,\n location: nextLocation,\n delta: 1\n });\n }\n },\n replace(to, state) {\n action = Action.Replace;\n let nextLocation = createMemoryLocation(to, state);\n entries[index] = nextLocation;\n if (v5Compat && listener) {\n listener({\n action,\n location: nextLocation,\n delta: 0\n });\n }\n },\n go(delta) {\n action = Action.Pop;\n let nextIndex = clampIndex(index + delta);\n let nextLocation = entries[nextIndex];\n index = nextIndex;\n if (listener) {\n listener({\n action,\n location: nextLocation,\n delta\n });\n }\n },\n listen(fn) {\n listener = fn;\n return () => {\n listener = null;\n };\n }\n };\n return history;\n}\n/**\n * Browser history stores the location in regular URLs. This is the standard for\n * most web apps, but it requires some configuration on the server to ensure you\n * serve the same app at multiple URLs.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory\n */\nfunction createBrowserHistory(options) {\n if (options === void 0) {\n options = {};\n }\n function createBrowserLocation(window, globalHistory) {\n let {\n pathname,\n search,\n hash\n } = window.location;\n return createLocation(\"\", {\n pathname,\n search,\n hash\n },\n // state defaults to `null` because `window.history.state` does\n globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || \"default\");\n }\n function createBrowserHref(window, to) {\n return typeof to === \"string\" ? to : createPath(to);\n }\n return getUrlBasedHistory(createBrowserLocation, createBrowserHref, null, options);\n}\n/**\n * Hash history stores the location in window.location.hash. This makes it ideal\n * for situations where you don't want to send the location to the server for\n * some reason, either because you do cannot configure it or the URL space is\n * reserved for something else.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory\n */\nfunction createHashHistory(options) {\n if (options === void 0) {\n options = {};\n }\n function createHashLocation(window, globalHistory) {\n let {\n pathname = \"/\",\n search = \"\",\n hash = \"\"\n } = parsePath(window.location.hash.substr(1));\n // Hash URL should always have a leading / just like window.location.pathname\n // does, so if an app ends up at a route like /#something then we add a\n // leading slash so all of our path-matching behaves the same as if it would\n // in a browser router. This is particularly important when there exists a\n // root splat route () since that matches internally against\n // \"/*\" and we'd expect /#something to 404 in a hash router app.\n if (!pathname.startsWith(\"/\") && !pathname.startsWith(\".\")) {\n pathname = \"/\" + pathname;\n }\n return createLocation(\"\", {\n pathname,\n search,\n hash\n },\n // state defaults to `null` because `window.history.state` does\n globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || \"default\");\n }\n function createHashHref(window, to) {\n let base = window.document.querySelector(\"base\");\n let href = \"\";\n if (base && base.getAttribute(\"href\")) {\n let url = window.location.href;\n let hashIndex = url.indexOf(\"#\");\n href = hashIndex === -1 ? url : url.slice(0, hashIndex);\n }\n return href + \"#\" + (typeof to === \"string\" ? to : createPath(to));\n }\n function validateHashLocation(location, to) {\n warning(location.pathname.charAt(0) === \"/\", \"relative pathnames are not supported in hash history.push(\" + JSON.stringify(to) + \")\");\n }\n return getUrlBasedHistory(createHashLocation, createHashHref, validateHashLocation, options);\n}\nfunction invariant(value, message) {\n if (value === false || value === null || typeof value === \"undefined\") {\n throw new Error(message);\n }\n}\nfunction warning(cond, message) {\n if (!cond) {\n // eslint-disable-next-line no-console\n if (typeof console !== \"undefined\") console.warn(message);\n try {\n // Welcome to debugging history!\n //\n // This error is thrown as a convenience, so you can more easily\n // find the source for a warning that appears in the console by\n // enabling \"pause on exceptions\" in your JavaScript debugger.\n throw new Error(message);\n // eslint-disable-next-line no-empty\n } catch (e) {}\n }\n}\nfunction createKey() {\n return Math.random().toString(36).substr(2, 8);\n}\n/**\n * For browser-based histories, we combine the state and key into an object\n */\nfunction getHistoryState(location, index) {\n return {\n usr: location.state,\n key: location.key,\n idx: index\n };\n}\n/**\n * Creates a Location object with a unique key from the given Path\n */\nfunction createLocation(current, to, state, key) {\n if (state === void 0) {\n state = null;\n }\n let location = _extends({\n pathname: typeof current === \"string\" ? current : current.pathname,\n search: \"\",\n hash: \"\"\n }, typeof to === \"string\" ? parsePath(to) : to, {\n state,\n // TODO: This could be cleaned up. push/replace should probably just take\n // full Locations now and avoid the need to run through this flow at all\n // But that's a pretty big refactor to the current test suite so going to\n // keep as is for the time being and just let any incoming keys take precedence\n key: to && to.key || key || createKey()\n });\n return location;\n}\n/**\n * Creates a string URL path from the given pathname, search, and hash components.\n */\nfunction createPath(_ref) {\n let {\n pathname = \"/\",\n search = \"\",\n hash = \"\"\n } = _ref;\n if (search && search !== \"?\") pathname += search.charAt(0) === \"?\" ? search : \"?\" + search;\n if (hash && hash !== \"#\") pathname += hash.charAt(0) === \"#\" ? hash : \"#\" + hash;\n return pathname;\n}\n/**\n * Parses a string URL path into its separate pathname, search, and hash components.\n */\nfunction parsePath(path) {\n let parsedPath = {};\n if (path) {\n let hashIndex = path.indexOf(\"#\");\n if (hashIndex >= 0) {\n parsedPath.hash = path.substr(hashIndex);\n path = path.substr(0, hashIndex);\n }\n let searchIndex = path.indexOf(\"?\");\n if (searchIndex >= 0) {\n parsedPath.search = path.substr(searchIndex);\n path = path.substr(0, searchIndex);\n }\n if (path) {\n parsedPath.pathname = path;\n }\n }\n return parsedPath;\n}\nfunction getUrlBasedHistory(getLocation, createHref, validateLocation, options) {\n if (options === void 0) {\n options = {};\n }\n let {\n window = document.defaultView,\n v5Compat = false\n } = options;\n let globalHistory = window.history;\n let action = Action.Pop;\n let listener = null;\n let index = getIndex();\n // Index should only be null when we initialize. If not, it's because the\n // user called history.pushState or history.replaceState directly, in which\n // case we should log a warning as it will result in bugs.\n if (index == null) {\n index = 0;\n globalHistory.replaceState(_extends({}, globalHistory.state, {\n idx: index\n }), \"\");\n }\n function getIndex() {\n let state = globalHistory.state || {\n idx: null\n };\n return state.idx;\n }\n function handlePop() {\n action = Action.Pop;\n let nextIndex = getIndex();\n let delta = nextIndex == null ? null : nextIndex - index;\n index = nextIndex;\n if (listener) {\n listener({\n action,\n location: history.location,\n delta\n });\n }\n }\n function push(to, state) {\n action = Action.Push;\n let location = createLocation(history.location, to, state);\n if (validateLocation) validateLocation(location, to);\n index = getIndex() + 1;\n let historyState = getHistoryState(location, index);\n let url = history.createHref(location);\n // try...catch because iOS limits us to 100 pushState calls :/\n try {\n globalHistory.pushState(historyState, \"\", url);\n } catch (error) {\n // If the exception is because `state` can't be serialized, let that throw\n // outwards just like a replace call would so the dev knows the cause\n // https://html.spec.whatwg.org/multipage/nav-history-apis.html#shared-history-push/replace-state-steps\n // https://html.spec.whatwg.org/multipage/structured-data.html#structuredserializeinternal\n if (error instanceof DOMException && error.name === \"DataCloneError\") {\n throw error;\n }\n // They are going to lose state here, but there is no real\n // way to warn them about it since the page will refresh...\n window.location.assign(url);\n }\n if (v5Compat && listener) {\n listener({\n action,\n location: history.location,\n delta: 1\n });\n }\n }\n function replace(to, state) {\n action = Action.Replace;\n let location = createLocation(history.location, to, state);\n if (validateLocation) validateLocation(location, to);\n index = getIndex();\n let historyState = getHistoryState(location, index);\n let url = history.createHref(location);\n globalHistory.replaceState(historyState, \"\", url);\n if (v5Compat && listener) {\n listener({\n action,\n location: history.location,\n delta: 0\n });\n }\n }\n function createURL(to) {\n // window.location.origin is \"null\" (the literal string value) in Firefox\n // under certain conditions, notably when serving from a local HTML file\n // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297\n let base = window.location.origin !== \"null\" ? window.location.origin : window.location.href;\n let href = typeof to === \"string\" ? to : createPath(to);\n // Treating this as a full URL will strip any trailing spaces so we need to\n // pre-encode them since they might be part of a matching splat param from\n // an ancestor route\n href = href.replace(/ $/, \"%20\");\n invariant(base, \"No window.location.(origin|href) available to create URL for href: \" + href);\n return new URL(href, base);\n }\n let history = {\n get action() {\n return action;\n },\n get location() {\n return getLocation(window, globalHistory);\n },\n listen(fn) {\n if (listener) {\n throw new Error(\"A history only accepts one active listener\");\n }\n window.addEventListener(PopStateEventType, handlePop);\n listener = fn;\n return () => {\n window.removeEventListener(PopStateEventType, handlePop);\n listener = null;\n };\n },\n createHref(to) {\n return createHref(window, to);\n },\n createURL,\n encodeLocation(to) {\n // Encode a Location the same way window.location would\n let url = createURL(to);\n return {\n pathname: url.pathname,\n search: url.search,\n hash: url.hash\n };\n },\n push,\n replace,\n go(n) {\n return globalHistory.go(n);\n }\n };\n return history;\n}\n//#endregion\n\nvar ResultType;\n(function (ResultType) {\n ResultType[\"data\"] = \"data\";\n ResultType[\"deferred\"] = \"deferred\";\n ResultType[\"redirect\"] = \"redirect\";\n ResultType[\"error\"] = \"error\";\n})(ResultType || (ResultType = {}));\nconst immutableRouteKeys = new Set([\"lazy\", \"caseSensitive\", \"path\", \"id\", \"index\", \"children\"]);\nfunction isIndexRoute(route) {\n return route.index === true;\n}\n// Walk the route tree generating unique IDs where necessary, so we are working\n// solely with AgnosticDataRouteObject's within the Router\nfunction convertRoutesToDataRoutes(routes, mapRouteProperties, parentPath, manifest) {\n if (parentPath === void 0) {\n parentPath = [];\n }\n if (manifest === void 0) {\n manifest = {};\n }\n return routes.map((route, index) => {\n let treePath = [...parentPath, String(index)];\n let id = typeof route.id === \"string\" ? route.id : treePath.join(\"-\");\n invariant(route.index !== true || !route.children, \"Cannot specify children on an index route\");\n invariant(!manifest[id], \"Found a route id collision on id \\\"\" + id + \"\\\". Route \" + \"id's must be globally unique within Data Router usages\");\n if (isIndexRoute(route)) {\n let indexRoute = _extends({}, route, mapRouteProperties(route), {\n id\n });\n manifest[id] = indexRoute;\n return indexRoute;\n } else {\n let pathOrLayoutRoute = _extends({}, route, mapRouteProperties(route), {\n id,\n children: undefined\n });\n manifest[id] = pathOrLayoutRoute;\n if (route.children) {\n pathOrLayoutRoute.children = convertRoutesToDataRoutes(route.children, mapRouteProperties, treePath, manifest);\n }\n return pathOrLayoutRoute;\n }\n });\n}\n/**\n * Matches the given routes to a location and returns the match data.\n *\n * @see https://reactrouter.com/utils/match-routes\n */\nfunction matchRoutes(routes, locationArg, basename) {\n if (basename === void 0) {\n basename = \"/\";\n }\n return matchRoutesImpl(routes, locationArg, basename, false);\n}\nfunction matchRoutesImpl(routes, locationArg, basename, allowPartial) {\n let location = typeof locationArg === \"string\" ? parsePath(locationArg) : locationArg;\n let pathname = stripBasename(location.pathname || \"/\", basename);\n if (pathname == null) {\n return null;\n }\n let branches = flattenRoutes(routes);\n rankRouteBranches(branches);\n let matches = null;\n for (let i = 0; matches == null && i < branches.length; ++i) {\n // Incoming pathnames are generally encoded from either window.location\n // or from router.navigate, but we want to match against the unencoded\n // paths in the route definitions. Memory router locations won't be\n // encoded here but there also shouldn't be anything to decode so this\n // should be a safe operation. This avoids needing matchRoutes to be\n // history-aware.\n let decoded = decodePath(pathname);\n matches = matchRouteBranch(branches[i], decoded, allowPartial);\n }\n return matches;\n}\nfunction convertRouteMatchToUiMatch(match, loaderData) {\n let {\n route,\n pathname,\n params\n } = match;\n return {\n id: route.id,\n pathname,\n params,\n data: loaderData[route.id],\n handle: route.handle\n };\n}\nfunction flattenRoutes(routes, branches, parentsMeta, parentPath) {\n if (branches === void 0) {\n branches = [];\n }\n if (parentsMeta === void 0) {\n parentsMeta = [];\n }\n if (parentPath === void 0) {\n parentPath = \"\";\n }\n let flattenRoute = (route, index, relativePath) => {\n let meta = {\n relativePath: relativePath === undefined ? route.path || \"\" : relativePath,\n caseSensitive: route.caseSensitive === true,\n childrenIndex: index,\n route\n };\n if (meta.relativePath.startsWith(\"/\")) {\n invariant(meta.relativePath.startsWith(parentPath), \"Absolute route path \\\"\" + meta.relativePath + \"\\\" nested under path \" + (\"\\\"\" + parentPath + \"\\\" is not valid. An absolute child route path \") + \"must start with the combined path of all its parent routes.\");\n meta.relativePath = meta.relativePath.slice(parentPath.length);\n }\n let path = joinPaths([parentPath, meta.relativePath]);\n let routesMeta = parentsMeta.concat(meta);\n // Add the children before adding this route to the array, so we traverse the\n // route tree depth-first and child routes appear before their parents in\n // the \"flattened\" version.\n if (route.children && route.children.length > 0) {\n invariant(\n // Our types know better, but runtime JS may not!\n // @ts-expect-error\n route.index !== true, \"Index routes must not have child routes. Please remove \" + (\"all child routes from route path \\\"\" + path + \"\\\".\"));\n flattenRoutes(route.children, branches, routesMeta, path);\n }\n // Routes without a path shouldn't ever match by themselves unless they are\n // index routes, so don't add them to the list of possible branches.\n if (route.path == null && !route.index) {\n return;\n }\n branches.push({\n path,\n score: computeScore(path, route.index),\n routesMeta\n });\n };\n routes.forEach((route, index) => {\n var _route$path;\n // coarse-grain check for optional params\n if (route.path === \"\" || !((_route$path = route.path) != null && _route$path.includes(\"?\"))) {\n flattenRoute(route, index);\n } else {\n for (let exploded of explodeOptionalSegments(route.path)) {\n flattenRoute(route, index, exploded);\n }\n }\n });\n return branches;\n}\n/**\n * Computes all combinations of optional path segments for a given path,\n * excluding combinations that are ambiguous and of lower priority.\n *\n * For example, `/one/:two?/three/:four?/:five?` explodes to:\n * - `/one/three`\n * - `/one/:two/three`\n * - `/one/three/:four`\n * - `/one/three/:five`\n * - `/one/:two/three/:four`\n * - `/one/:two/three/:five`\n * - `/one/three/:four/:five`\n * - `/one/:two/three/:four/:five`\n */\nfunction explodeOptionalSegments(path) {\n let segments = path.split(\"/\");\n if (segments.length === 0) return [];\n let [first, ...rest] = segments;\n // Optional path segments are denoted by a trailing `?`\n let isOptional = first.endsWith(\"?\");\n // Compute the corresponding required segment: `foo?` -> `foo`\n let required = first.replace(/\\?$/, \"\");\n if (rest.length === 0) {\n // Intepret empty string as omitting an optional segment\n // `[\"one\", \"\", \"three\"]` corresponds to omitting `:two` from `/one/:two?/three` -> `/one/three`\n return isOptional ? [required, \"\"] : [required];\n }\n let restExploded = explodeOptionalSegments(rest.join(\"/\"));\n let result = [];\n // All child paths with the prefix. Do this for all children before the\n // optional version for all children, so we get consistent ordering where the\n // parent optional aspect is preferred as required. Otherwise, we can get\n // child sections interspersed where deeper optional segments are higher than\n // parent optional segments, where for example, /:two would explode _earlier_\n // then /:one. By always including the parent as required _for all children_\n // first, we avoid this issue\n result.push(...restExploded.map(subpath => subpath === \"\" ? required : [required, subpath].join(\"/\")));\n // Then, if this is an optional value, add all child versions without\n if (isOptional) {\n result.push(...restExploded);\n }\n // for absolute paths, ensure `/` instead of empty segment\n return result.map(exploded => path.startsWith(\"/\") && exploded === \"\" ? \"/\" : exploded);\n}\nfunction rankRouteBranches(branches) {\n branches.sort((a, b) => a.score !== b.score ? b.score - a.score // Higher score first\n : compareIndexes(a.routesMeta.map(meta => meta.childrenIndex), b.routesMeta.map(meta => meta.childrenIndex)));\n}\nconst paramRe = /^:[\\w-]+$/;\nconst dynamicSegmentValue = 3;\nconst indexRouteValue = 2;\nconst emptySegmentValue = 1;\nconst staticSegmentValue = 10;\nconst splatPenalty = -2;\nconst isSplat = s => s === \"*\";\nfunction computeScore(path, index) {\n let segments = path.split(\"/\");\n let initialScore = segments.length;\n if (segments.some(isSplat)) {\n initialScore += splatPenalty;\n }\n if (index) {\n initialScore += indexRouteValue;\n }\n return segments.filter(s => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === \"\" ? emptySegmentValue : staticSegmentValue), initialScore);\n}\nfunction compareIndexes(a, b) {\n let siblings = a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);\n return siblings ?\n // If two routes are siblings, we should try to match the earlier sibling\n // first. This allows people to have fine-grained control over the matching\n // behavior by simply putting routes with identical paths in the order they\n // want them tried.\n a[a.length - 1] - b[b.length - 1] :\n // Otherwise, it doesn't really make sense to rank non-siblings by index,\n // so they sort equally.\n 0;\n}\nfunction matchRouteBranch(branch, pathname, allowPartial) {\n if (allowPartial === void 0) {\n allowPartial = false;\n }\n let {\n routesMeta\n } = branch;\n let matchedParams = {};\n let matchedPathname = \"/\";\n let matches = [];\n for (let i = 0; i < routesMeta.length; ++i) {\n let meta = routesMeta[i];\n let end = i === routesMeta.length - 1;\n let remainingPathname = matchedPathname === \"/\" ? pathname : pathname.slice(matchedPathname.length) || \"/\";\n let match = matchPath({\n path: meta.relativePath,\n caseSensitive: meta.caseSensitive,\n end\n }, remainingPathname);\n let route = meta.route;\n if (!match && end && allowPartial && !routesMeta[routesMeta.length - 1].route.index) {\n match = matchPath({\n path: meta.relativePath,\n caseSensitive: meta.caseSensitive,\n end: false\n }, remainingPathname);\n }\n if (!match) {\n return null;\n }\n Object.assign(matchedParams, match.params);\n matches.push({\n // TODO: Can this as be avoided?\n params: matchedParams,\n pathname: joinPaths([matchedPathname, match.pathname]),\n pathnameBase: normalizePathname(joinPaths([matchedPathname, match.pathnameBase])),\n route\n });\n if (match.pathnameBase !== \"/\") {\n matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);\n }\n }\n return matches;\n}\n/**\n * Returns a path with params interpolated.\n *\n * @see https://reactrouter.com/utils/generate-path\n */\nfunction generatePath(originalPath, params) {\n if (params === void 0) {\n params = {};\n }\n let path = originalPath;\n if (path.endsWith(\"*\") && path !== \"*\" && !path.endsWith(\"/*\")) {\n warning(false, \"Route path \\\"\" + path + \"\\\" will be treated as if it were \" + (\"\\\"\" + path.replace(/\\*$/, \"/*\") + \"\\\" because the `*` character must \") + \"always follow a `/` in the pattern. To get rid of this warning, \" + (\"please change the route path to \\\"\" + path.replace(/\\*$/, \"/*\") + \"\\\".\"));\n path = path.replace(/\\*$/, \"/*\");\n }\n // ensure `/` is added at the beginning if the path is absolute\n const prefix = path.startsWith(\"/\") ? \"/\" : \"\";\n const stringify = p => p == null ? \"\" : typeof p === \"string\" ? p : String(p);\n const segments = path.split(/\\/+/).map((segment, index, array) => {\n const isLastSegment = index === array.length - 1;\n // only apply the splat if it's the last segment\n if (isLastSegment && segment === \"*\") {\n const star = \"*\";\n // Apply the splat\n return stringify(params[star]);\n }\n const keyMatch = segment.match(/^:([\\w-]+)(\\??)$/);\n if (keyMatch) {\n const [, key, optional] = keyMatch;\n let param = params[key];\n invariant(optional === \"?\" || param != null, \"Missing \\\":\" + key + \"\\\" param\");\n return stringify(param);\n }\n // Remove any optional markers from optional static segments\n return segment.replace(/\\?$/g, \"\");\n })\n // Remove empty segments\n .filter(segment => !!segment);\n return prefix + segments.join(\"/\");\n}\n/**\n * Performs pattern matching on a URL pathname and returns information about\n * the match.\n *\n * @see https://reactrouter.com/utils/match-path\n */\nfunction matchPath(pattern, pathname) {\n if (typeof pattern === \"string\") {\n pattern = {\n path: pattern,\n caseSensitive: false,\n end: true\n };\n }\n let [matcher, compiledParams] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);\n let match = pathname.match(matcher);\n if (!match) return null;\n let matchedPathname = match[0];\n let pathnameBase = matchedPathname.replace(/(.)\\/+$/, \"$1\");\n let captureGroups = match.slice(1);\n let params = compiledParams.reduce((memo, _ref, index) => {\n let {\n paramName,\n isOptional\n } = _ref;\n // We need to compute the pathnameBase here using the raw splat value\n // instead of using params[\"*\"] later because it will be decoded then\n if (paramName === \"*\") {\n let splatValue = captureGroups[index] || \"\";\n pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\\/+$/, \"$1\");\n }\n const value = captureGroups[index];\n if (isOptional && !value) {\n memo[paramName] = undefined;\n } else {\n memo[paramName] = (value || \"\").replace(/%2F/g, \"/\");\n }\n return memo;\n }, {});\n return {\n params,\n pathname: matchedPathname,\n pathnameBase,\n pattern\n };\n}\nfunction compilePath(path, caseSensitive, end) {\n if (caseSensitive === void 0) {\n caseSensitive = false;\n }\n if (end === void 0) {\n end = true;\n }\n warning(path === \"*\" || !path.endsWith(\"*\") || path.endsWith(\"/*\"), \"Route path \\\"\" + path + \"\\\" will be treated as if it were \" + (\"\\\"\" + path.replace(/\\*$/, \"/*\") + \"\\\" because the `*` character must \") + \"always follow a `/` in the pattern. To get rid of this warning, \" + (\"please change the route path to \\\"\" + path.replace(/\\*$/, \"/*\") + \"\\\".\"));\n let params = [];\n let regexpSource = \"^\" + path.replace(/\\/*\\*?$/, \"\") // Ignore trailing / and /*, we'll handle it below\n .replace(/^\\/*/, \"/\") // Make sure it has a leading /\n .replace(/[\\\\.*+^${}|()[\\]]/g, \"\\\\$&\") // Escape special regex chars\n .replace(/\\/:([\\w-]+)(\\?)?/g, (_, paramName, isOptional) => {\n params.push({\n paramName,\n isOptional: isOptional != null\n });\n return isOptional ? \"/?([^\\\\/]+)?\" : \"/([^\\\\/]+)\";\n });\n if (path.endsWith(\"*\")) {\n params.push({\n paramName: \"*\"\n });\n regexpSource += path === \"*\" || path === \"/*\" ? \"(.*)$\" // Already matched the initial /, just match the rest\n : \"(?:\\\\/(.+)|\\\\/*)$\"; // Don't include the / in params[\"*\"]\n } else if (end) {\n // When matching to the end, ignore trailing slashes\n regexpSource += \"\\\\/*$\";\n } else if (path !== \"\" && path !== \"/\") {\n // If our path is non-empty and contains anything beyond an initial slash,\n // then we have _some_ form of path in our regex, so we should expect to\n // match only if we find the end of this path segment. Look for an optional\n // non-captured trailing slash (to match a portion of the URL) or the end\n // of the path (if we've matched to the end). We used to do this with a\n // word boundary but that gives false positives on routes like\n // /user-preferences since `-` counts as a word boundary.\n regexpSource += \"(?:(?=\\\\/|$))\";\n } else ;\n let matcher = new RegExp(regexpSource, caseSensitive ? undefined : \"i\");\n return [matcher, params];\n}\nfunction decodePath(value) {\n try {\n return value.split(\"/\").map(v => decodeURIComponent(v).replace(/\\//g, \"%2F\")).join(\"/\");\n } catch (error) {\n warning(false, \"The URL path \\\"\" + value + \"\\\" could not be decoded because it is is a \" + \"malformed URL segment. This is probably due to a bad percent \" + (\"encoding (\" + error + \").\"));\n return value;\n }\n}\n/**\n * @private\n */\nfunction stripBasename(pathname, basename) {\n if (basename === \"/\") return pathname;\n if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {\n return null;\n }\n // We want to leave trailing slash behavior in the user's control, so if they\n // specify a basename with a trailing slash, we should support it\n let startIndex = basename.endsWith(\"/\") ? basename.length - 1 : basename.length;\n let nextChar = pathname.charAt(startIndex);\n if (nextChar && nextChar !== \"/\") {\n // pathname does not start with basename/\n return null;\n }\n return pathname.slice(startIndex) || \"/\";\n}\n/**\n * Returns a resolved path object relative to the given pathname.\n *\n * @see https://reactrouter.com/utils/resolve-path\n */\nfunction resolvePath(to, fromPathname) {\n if (fromPathname === void 0) {\n fromPathname = \"/\";\n }\n let {\n pathname: toPathname,\n search = \"\",\n hash = \"\"\n } = typeof to === \"string\" ? parsePath(to) : to;\n let pathname = toPathname ? toPathname.startsWith(\"/\") ? toPathname : resolvePathname(toPathname, fromPathname) : fromPathname;\n return {\n pathname,\n search: normalizeSearch(search),\n hash: normalizeHash(hash)\n };\n}\nfunction resolvePathname(relativePath, fromPathname) {\n let segments = fromPathname.replace(/\\/+$/, \"\").split(\"/\");\n let relativeSegments = relativePath.split(\"/\");\n relativeSegments.forEach(segment => {\n if (segment === \"..\") {\n // Keep the root \"\" segment so the pathname starts at /\n if (segments.length > 1) segments.pop();\n } else if (segment !== \".\") {\n segments.push(segment);\n }\n });\n return segments.length > 1 ? segments.join(\"/\") : \"/\";\n}\nfunction getInvalidPathError(char, field, dest, path) {\n return \"Cannot include a '\" + char + \"' character in a manually specified \" + (\"`to.\" + field + \"` field [\" + JSON.stringify(path) + \"]. Please separate it out to the \") + (\"`to.\" + dest + \"` field. Alternatively you may provide the full path as \") + \"a string in and the router will parse it for you.\";\n}\n/**\n * @private\n *\n * When processing relative navigation we want to ignore ancestor routes that\n * do not contribute to the path, such that index/pathless layout routes don't\n * interfere.\n *\n * For example, when moving a route element into an index route and/or a\n * pathless layout route, relative link behavior contained within should stay\n * the same. Both of the following examples should link back to the root:\n *\n * \n * \n * \n *\n * \n * \n * }> // <-- Does not contribute\n * // <-- Does not contribute\n * \n * \n */\nfunction getPathContributingMatches(matches) {\n return matches.filter((match, index) => index === 0 || match.route.path && match.route.path.length > 0);\n}\n// Return the array of pathnames for the current route matches - used to\n// generate the routePathnames input for resolveTo()\nfunction getResolveToMatches(matches, v7_relativeSplatPath) {\n let pathMatches = getPathContributingMatches(matches);\n // When v7_relativeSplatPath is enabled, use the full pathname for the leaf\n // match so we include splat values for \".\" links. See:\n // https://github.com/remix-run/react-router/issues/11052#issuecomment-1836589329\n if (v7_relativeSplatPath) {\n return pathMatches.map((match, idx) => idx === pathMatches.length - 1 ? match.pathname : match.pathnameBase);\n }\n return pathMatches.map(match => match.pathnameBase);\n}\n/**\n * @private\n */\nfunction resolveTo(toArg, routePathnames, locationPathname, isPathRelative) {\n if (isPathRelative === void 0) {\n isPathRelative = false;\n }\n let to;\n if (typeof toArg === \"string\") {\n to = parsePath(toArg);\n } else {\n to = _extends({}, toArg);\n invariant(!to.pathname || !to.pathname.includes(\"?\"), getInvalidPathError(\"?\", \"pathname\", \"search\", to));\n invariant(!to.pathname || !to.pathname.includes(\"#\"), getInvalidPathError(\"#\", \"pathname\", \"hash\", to));\n invariant(!to.search || !to.search.includes(\"#\"), getInvalidPathError(\"#\", \"search\", \"hash\", to));\n }\n let isEmptyPath = toArg === \"\" || to.pathname === \"\";\n let toPathname = isEmptyPath ? \"/\" : to.pathname;\n let from;\n // Routing is relative to the current pathname if explicitly requested.\n //\n // If a pathname is explicitly provided in `to`, it should be relative to the\n // route context. This is explained in `Note on `` values` in our\n // migration guide from v5 as a means of disambiguation between `to` values\n // that begin with `/` and those that do not. However, this is problematic for\n // `to` values that do not provide a pathname. `to` can simply be a search or\n // hash string, in which case we should assume that the navigation is relative\n // to the current location's pathname and *not* the route pathname.\n if (toPathname == null) {\n from = locationPathname;\n } else {\n let routePathnameIndex = routePathnames.length - 1;\n // With relative=\"route\" (the default), each leading .. segment means\n // \"go up one route\" instead of \"go up one URL segment\". This is a key\n // difference from how works and a major reason we call this a\n // \"to\" value instead of a \"href\".\n if (!isPathRelative && toPathname.startsWith(\"..\")) {\n let toSegments = toPathname.split(\"/\");\n while (toSegments[0] === \"..\") {\n toSegments.shift();\n routePathnameIndex -= 1;\n }\n to.pathname = toSegments.join(\"/\");\n }\n from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : \"/\";\n }\n let path = resolvePath(to, from);\n // Ensure the pathname has a trailing slash if the original \"to\" had one\n let hasExplicitTrailingSlash = toPathname && toPathname !== \"/\" && toPathname.endsWith(\"/\");\n // Or if this was a link to the current path which has a trailing slash\n let hasCurrentTrailingSlash = (isEmptyPath || toPathname === \".\") && locationPathname.endsWith(\"/\");\n if (!path.pathname.endsWith(\"/\") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) {\n path.pathname += \"/\";\n }\n return path;\n}\n/**\n * @private\n */\nfunction getToPathname(to) {\n // Empty strings should be treated the same as / paths\n return to === \"\" || to.pathname === \"\" ? \"/\" : typeof to === \"string\" ? parsePath(to).pathname : to.pathname;\n}\n/**\n * @private\n */\nconst joinPaths = paths => paths.join(\"/\").replace(/\\/\\/+/g, \"/\");\n/**\n * @private\n */\nconst normalizePathname = pathname => pathname.replace(/\\/+$/, \"\").replace(/^\\/*/, \"/\");\n/**\n * @private\n */\nconst normalizeSearch = search => !search || search === \"?\" ? \"\" : search.startsWith(\"?\") ? search : \"?\" + search;\n/**\n * @private\n */\nconst normalizeHash = hash => !hash || hash === \"#\" ? \"\" : hash.startsWith(\"#\") ? hash : \"#\" + hash;\n/**\n * This is a shortcut for creating `application/json` responses. Converts `data`\n * to JSON and sets the `Content-Type` header.\n */\nconst json = function json(data, init) {\n if (init === void 0) {\n init = {};\n }\n let responseInit = typeof init === \"number\" ? {\n status: init\n } : init;\n let headers = new Headers(responseInit.headers);\n if (!headers.has(\"Content-Type\")) {\n headers.set(\"Content-Type\", \"application/json; charset=utf-8\");\n }\n return new Response(JSON.stringify(data), _extends({}, responseInit, {\n headers\n }));\n};\nclass DataWithResponseInit {\n constructor(data, init) {\n this.type = \"DataWithResponseInit\";\n this.data = data;\n this.init = init || null;\n }\n}\n/**\n * Create \"responses\" that contain `status`/`headers` without forcing\n * serialization into an actual `Response` - used by Remix single fetch\n */\nfunction data(data, init) {\n return new DataWithResponseInit(data, typeof init === \"number\" ? {\n status: init\n } : init);\n}\nclass AbortedDeferredError extends Error {}\nclass DeferredData {\n constructor(data, responseInit) {\n this.pendingKeysSet = new Set();\n this.subscribers = new Set();\n this.deferredKeys = [];\n invariant(data && typeof data === \"object\" && !Array.isArray(data), \"defer() only accepts plain objects\");\n // Set up an AbortController + Promise we can race against to exit early\n // cancellation\n let reject;\n this.abortPromise = new Promise((_, r) => reject = r);\n this.controller = new AbortController();\n let onAbort = () => reject(new AbortedDeferredError(\"Deferred data aborted\"));\n this.unlistenAbortSignal = () => this.controller.signal.removeEventListener(\"abort\", onAbort);\n this.controller.signal.addEventListener(\"abort\", onAbort);\n this.data = Object.entries(data).reduce((acc, _ref2) => {\n let [key, value] = _ref2;\n return Object.assign(acc, {\n [key]: this.trackPromise(key, value)\n });\n }, {});\n if (this.done) {\n // All incoming values were resolved\n this.unlistenAbortSignal();\n }\n this.init = responseInit;\n }\n trackPromise(key, value) {\n if (!(value instanceof Promise)) {\n return value;\n }\n this.deferredKeys.push(key);\n this.pendingKeysSet.add(key);\n // We store a little wrapper promise that will be extended with\n // _data/_error props upon resolve/reject\n let promise = Promise.race([value, this.abortPromise]).then(data => this.onSettle(promise, key, undefined, data), error => this.onSettle(promise, key, error));\n // Register rejection listeners to avoid uncaught promise rejections on\n // errors or aborted deferred values\n promise.catch(() => {});\n Object.defineProperty(promise, \"_tracked\", {\n get: () => true\n });\n return promise;\n }\n onSettle(promise, key, error, data) {\n if (this.controller.signal.aborted && error instanceof AbortedDeferredError) {\n this.unlistenAbortSignal();\n Object.defineProperty(promise, \"_error\", {\n get: () => error\n });\n return Promise.reject(error);\n }\n this.pendingKeysSet.delete(key);\n if (this.done) {\n // Nothing left to abort!\n this.unlistenAbortSignal();\n }\n // If the promise was resolved/rejected with undefined, we'll throw an error as you\n // should always resolve with a value or null\n if (error === undefined && data === undefined) {\n let undefinedError = new Error(\"Deferred data for key \\\"\" + key + \"\\\" resolved/rejected with `undefined`, \" + \"you must resolve/reject with a value or `null`.\");\n Object.defineProperty(promise, \"_error\", {\n get: () => undefinedError\n });\n this.emit(false, key);\n return Promise.reject(undefinedError);\n }\n if (data === undefined) {\n Object.defineProperty(promise, \"_error\", {\n get: () => error\n });\n this.emit(false, key);\n return Promise.reject(error);\n }\n Object.defineProperty(promise, \"_data\", {\n get: () => data\n });\n this.emit(false, key);\n return data;\n }\n emit(aborted, settledKey) {\n this.subscribers.forEach(subscriber => subscriber(aborted, settledKey));\n }\n subscribe(fn) {\n this.subscribers.add(fn);\n return () => this.subscribers.delete(fn);\n }\n cancel() {\n this.controller.abort();\n this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k));\n this.emit(true);\n }\n async resolveData(signal) {\n let aborted = false;\n if (!this.done) {\n let onAbort = () => this.cancel();\n signal.addEventListener(\"abort\", onAbort);\n aborted = await new Promise(resolve => {\n this.subscribe(aborted => {\n signal.removeEventListener(\"abort\", onAbort);\n if (aborted || this.done) {\n resolve(aborted);\n }\n });\n });\n }\n return aborted;\n }\n get done() {\n return this.pendingKeysSet.size === 0;\n }\n get unwrappedData() {\n invariant(this.data !== null && this.done, \"Can only unwrap data on initialized and settled deferreds\");\n return Object.entries(this.data).reduce((acc, _ref3) => {\n let [key, value] = _ref3;\n return Object.assign(acc, {\n [key]: unwrapTrackedPromise(value)\n });\n }, {});\n }\n get pendingKeys() {\n return Array.from(this.pendingKeysSet);\n }\n}\nfunction isTrackedPromise(value) {\n return value instanceof Promise && value._tracked === true;\n}\nfunction unwrapTrackedPromise(value) {\n if (!isTrackedPromise(value)) {\n return value;\n }\n if (value._error) {\n throw value._error;\n }\n return value._data;\n}\nconst defer = function defer(data, init) {\n if (init === void 0) {\n init = {};\n }\n let responseInit = typeof init === \"number\" ? {\n status: init\n } : init;\n return new DeferredData(data, responseInit);\n};\n/**\n * A redirect response. Sets the status code and the `Location` header.\n * Defaults to \"302 Found\".\n */\nconst redirect = function redirect(url, init) {\n if (init === void 0) {\n init = 302;\n }\n let responseInit = init;\n if (typeof responseInit === \"number\") {\n responseInit = {\n status: responseInit\n };\n } else if (typeof responseInit.status === \"undefined\") {\n responseInit.status = 302;\n }\n let headers = new Headers(responseInit.headers);\n headers.set(\"Location\", url);\n return new Response(null, _extends({}, responseInit, {\n headers\n }));\n};\n/**\n * A redirect response that will force a document reload to the new location.\n * Sets the status code and the `Location` header.\n * Defaults to \"302 Found\".\n */\nconst redirectDocument = (url, init) => {\n let response = redirect(url, init);\n response.headers.set(\"X-Remix-Reload-Document\", \"true\");\n return response;\n};\n/**\n * A redirect response that will perform a `history.replaceState` instead of a\n * `history.pushState` for client-side navigation redirects.\n * Sets the status code and the `Location` header.\n * Defaults to \"302 Found\".\n */\nconst replace = (url, init) => {\n let response = redirect(url, init);\n response.headers.set(\"X-Remix-Replace\", \"true\");\n return response;\n};\n/**\n * @private\n * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies\n *\n * We don't export the class for public use since it's an implementation\n * detail, but we export the interface above so folks can build their own\n * abstractions around instances via isRouteErrorResponse()\n */\nclass ErrorResponseImpl {\n constructor(status, statusText, data, internal) {\n if (internal === void 0) {\n internal = false;\n }\n this.status = status;\n this.statusText = statusText || \"\";\n this.internal = internal;\n if (data instanceof Error) {\n this.data = data.toString();\n this.error = data;\n } else {\n this.data = data;\n }\n }\n}\n/**\n * Check if the given error is an ErrorResponse generated from a 4xx/5xx\n * Response thrown from an action/loader\n */\nfunction isRouteErrorResponse(error) {\n return error != null && typeof error.status === \"number\" && typeof error.statusText === \"string\" && typeof error.internal === \"boolean\" && \"data\" in error;\n}\n\nconst validMutationMethodsArr = [\"post\", \"put\", \"patch\", \"delete\"];\nconst validMutationMethods = new Set(validMutationMethodsArr);\nconst validRequestMethodsArr = [\"get\", ...validMutationMethodsArr];\nconst validRequestMethods = new Set(validRequestMethodsArr);\nconst redirectStatusCodes = new Set([301, 302, 303, 307, 308]);\nconst redirectPreserveMethodStatusCodes = new Set([307, 308]);\nconst IDLE_NAVIGATION = {\n state: \"idle\",\n location: undefined,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n json: undefined,\n text: undefined\n};\nconst IDLE_FETCHER = {\n state: \"idle\",\n data: undefined,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n json: undefined,\n text: undefined\n};\nconst IDLE_BLOCKER = {\n state: \"unblocked\",\n proceed: undefined,\n reset: undefined,\n location: undefined\n};\nconst ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\\/\\/)/i;\nconst defaultMapRouteProperties = route => ({\n hasErrorBoundary: Boolean(route.hasErrorBoundary)\n});\nconst TRANSITIONS_STORAGE_KEY = \"remix-router-transitions\";\n//#endregion\n////////////////////////////////////////////////////////////////////////////////\n//#region createRouter\n////////////////////////////////////////////////////////////////////////////////\n/**\n * Create a router and listen to history POP navigations\n */\nfunction createRouter(init) {\n const routerWindow = init.window ? init.window : typeof window !== \"undefined\" ? window : undefined;\n const isBrowser = typeof routerWindow !== \"undefined\" && typeof routerWindow.document !== \"undefined\" && typeof routerWindow.document.createElement !== \"undefined\";\n const isServer = !isBrowser;\n invariant(init.routes.length > 0, \"You must provide a non-empty routes array to createRouter\");\n let mapRouteProperties;\n if (init.mapRouteProperties) {\n mapRouteProperties = init.mapRouteProperties;\n } else if (init.detectErrorBoundary) {\n // If they are still using the deprecated version, wrap it with the new API\n let detectErrorBoundary = init.detectErrorBoundary;\n mapRouteProperties = route => ({\n hasErrorBoundary: detectErrorBoundary(route)\n });\n } else {\n mapRouteProperties = defaultMapRouteProperties;\n }\n // Routes keyed by ID\n let manifest = {};\n // Routes in tree format for matching\n let dataRoutes = convertRoutesToDataRoutes(init.routes, mapRouteProperties, undefined, manifest);\n let inFlightDataRoutes;\n let basename = init.basename || \"/\";\n let dataStrategyImpl = init.unstable_dataStrategy || defaultDataStrategy;\n let patchRoutesOnNavigationImpl = init.unstable_patchRoutesOnNavigation;\n // Config driven behavior flags\n let future = _extends({\n v7_fetcherPersist: false,\n v7_normalizeFormMethod: false,\n v7_partialHydration: false,\n v7_prependBasename: false,\n v7_relativeSplatPath: false,\n v7_skipActionErrorRevalidation: false\n }, init.future);\n // Cleanup function for history\n let unlistenHistory = null;\n // Externally-provided functions to call on all state changes\n let subscribers = new Set();\n // FIFO queue of previously discovered routes to prevent re-calling on\n // subsequent navigations to the same path\n let discoveredRoutesMaxSize = 1000;\n let discoveredRoutes = new Set();\n // Externally-provided object to hold scroll restoration locations during routing\n let savedScrollPositions = null;\n // Externally-provided function to get scroll restoration keys\n let getScrollRestorationKey = null;\n // Externally-provided function to get current scroll position\n let getScrollPosition = null;\n // One-time flag to control the initial hydration scroll restoration. Because\n // we don't get the saved positions from until _after_\n // the initial render, we need to manually trigger a separate updateState to\n // send along the restoreScrollPosition\n // Set to true if we have `hydrationData` since we assume we were SSR'd and that\n // SSR did the initial scroll restoration.\n let initialScrollRestored = init.hydrationData != null;\n let initialMatches = matchRoutes(dataRoutes, init.history.location, basename);\n let initialErrors = null;\n if (initialMatches == null && !patchRoutesOnNavigationImpl) {\n // If we do not match a user-provided-route, fall back to the root\n // to allow the error boundary to take over\n let error = getInternalRouterError(404, {\n pathname: init.history.location.pathname\n });\n let {\n matches,\n route\n } = getShortCircuitMatches(dataRoutes);\n initialMatches = matches;\n initialErrors = {\n [route.id]: error\n };\n }\n // In SPA apps, if the user provided a patchRoutesOnNavigation implementation and\n // our initial match is a splat route, clear them out so we run through lazy\n // discovery on hydration in case there's a more accurate lazy route match.\n // In SSR apps (with `hydrationData`), we expect that the server will send\n // up the proper matched routes so we don't want to run lazy discovery on\n // initial hydration and want to hydrate into the splat route.\n if (initialMatches && !init.hydrationData) {\n let fogOfWar = checkFogOfWar(initialMatches, dataRoutes, init.history.location.pathname);\n if (fogOfWar.active) {\n initialMatches = null;\n }\n }\n let initialized;\n if (!initialMatches) {\n initialized = false;\n initialMatches = [];\n // If partial hydration and fog of war is enabled, we will be running\n // `patchRoutesOnNavigation` during hydration so include any partial matches as\n // the initial matches so we can properly render `HydrateFallback`'s\n if (future.v7_partialHydration) {\n let fogOfWar = checkFogOfWar(null, dataRoutes, init.history.location.pathname);\n if (fogOfWar.active && fogOfWar.matches) {\n initialMatches = fogOfWar.matches;\n }\n }\n } else if (initialMatches.some(m => m.route.lazy)) {\n // All initialMatches need to be loaded before we're ready. If we have lazy\n // functions around still then we'll need to run them in initialize()\n initialized = false;\n } else if (!initialMatches.some(m => m.route.loader)) {\n // If we've got no loaders to run, then we're good to go\n initialized = true;\n } else if (future.v7_partialHydration) {\n // If partial hydration is enabled, we're initialized so long as we were\n // provided with hydrationData for every route with a loader, and no loaders\n // were marked for explicit hydration\n let loaderData = init.hydrationData ? init.hydrationData.loaderData : null;\n let errors = init.hydrationData ? init.hydrationData.errors : null;\n let isRouteInitialized = m => {\n // No loader, nothing to initialize\n if (!m.route.loader) {\n return true;\n }\n // Explicitly opting-in to running on hydration\n if (typeof m.route.loader === \"function\" && m.route.loader.hydrate === true) {\n return false;\n }\n // Otherwise, initialized if hydrated with data or an error\n return loaderData && loaderData[m.route.id] !== undefined || errors && errors[m.route.id] !== undefined;\n };\n // If errors exist, don't consider routes below the boundary\n if (errors) {\n let idx = initialMatches.findIndex(m => errors[m.route.id] !== undefined);\n initialized = initialMatches.slice(0, idx + 1).every(isRouteInitialized);\n } else {\n initialized = initialMatches.every(isRouteInitialized);\n }\n } else {\n // Without partial hydration - we're initialized if we were provided any\n // hydrationData - which is expected to be complete\n initialized = init.hydrationData != null;\n }\n let router;\n let state = {\n historyAction: init.history.action,\n location: init.history.location,\n matches: initialMatches,\n initialized,\n navigation: IDLE_NAVIGATION,\n // Don't restore on initial updateState() if we were SSR'd\n restoreScrollPosition: init.hydrationData != null ? false : null,\n preventScrollReset: false,\n revalidation: \"idle\",\n loaderData: init.hydrationData && init.hydrationData.loaderData || {},\n actionData: init.hydrationData && init.hydrationData.actionData || null,\n errors: init.hydrationData && init.hydrationData.errors || initialErrors,\n fetchers: new Map(),\n blockers: new Map()\n };\n // -- Stateful internal variables to manage navigations --\n // Current navigation in progress (to be committed in completeNavigation)\n let pendingAction = Action.Pop;\n // Should the current navigation prevent the scroll reset if scroll cannot\n // be restored?\n let pendingPreventScrollReset = false;\n // AbortController for the active navigation\n let pendingNavigationController;\n // Should the current navigation enable document.startViewTransition?\n let pendingViewTransitionEnabled = false;\n // Store applied view transitions so we can apply them on POP\n let appliedViewTransitions = new Map();\n // Cleanup function for persisting applied transitions to sessionStorage\n let removePageHideEventListener = null;\n // We use this to avoid touching history in completeNavigation if a\n // revalidation is entirely uninterrupted\n let isUninterruptedRevalidation = false;\n // Use this internal flag to force revalidation of all loaders:\n // - submissions (completed or interrupted)\n // - useRevalidator()\n // - X-Remix-Revalidate (from redirect)\n let isRevalidationRequired = false;\n // Use this internal array to capture routes that require revalidation due\n // to a cancelled deferred on action submission\n let cancelledDeferredRoutes = [];\n // Use this internal array to capture fetcher loads that were cancelled by an\n // action navigation and require revalidation\n let cancelledFetcherLoads = new Set();\n // AbortControllers for any in-flight fetchers\n let fetchControllers = new Map();\n // Track loads based on the order in which they started\n let incrementingLoadId = 0;\n // Track the outstanding pending navigation data load to be compared against\n // the globally incrementing load when a fetcher load lands after a completed\n // navigation\n let pendingNavigationLoadId = -1;\n // Fetchers that triggered data reloads as a result of their actions\n let fetchReloadIds = new Map();\n // Fetchers that triggered redirect navigations\n let fetchRedirectIds = new Set();\n // Most recent href/match for fetcher.load calls for fetchers\n let fetchLoadMatches = new Map();\n // Ref-count mounted fetchers so we know when it's ok to clean them up\n let activeFetchers = new Map();\n // Fetchers that have requested a delete when using v7_fetcherPersist,\n // they'll be officially removed after they return to idle\n let deletedFetchers = new Set();\n // Store DeferredData instances for active route matches. When a\n // route loader returns defer() we stick one in here. Then, when a nested\n // promise resolves we update loaderData. If a new navigation starts we\n // cancel active deferreds for eliminated routes.\n let activeDeferreds = new Map();\n // Store blocker functions in a separate Map outside of router state since\n // we don't need to update UI state if they change\n let blockerFunctions = new Map();\n // Map of pending patchRoutesOnNavigation() promises (keyed by path/matches) so\n // that we only kick them off once for a given combo\n let pendingPatchRoutes = new Map();\n // Flag to ignore the next history update, so we can revert the URL change on\n // a POP navigation that was blocked by the user without touching router state\n let unblockBlockerHistoryUpdate = undefined;\n // Initialize the router, all side effects should be kicked off from here.\n // Implemented as a Fluent API for ease of:\n // let router = createRouter(init).initialize();\n function initialize() {\n // If history informs us of a POP navigation, start the navigation but do not update\n // state. We'll update our own state once the navigation completes\n unlistenHistory = init.history.listen(_ref => {\n let {\n action: historyAction,\n location,\n delta\n } = _ref;\n // Ignore this event if it was just us resetting the URL from a\n // blocked POP navigation\n if (unblockBlockerHistoryUpdate) {\n unblockBlockerHistoryUpdate();\n unblockBlockerHistoryUpdate = undefined;\n return;\n }\n warning(blockerFunctions.size === 0 || delta != null, \"You are trying to use a blocker on a POP navigation to a location \" + \"that was not created by @remix-run/router. This will fail silently in \" + \"production. This can happen if you are navigating outside the router \" + \"via `window.history.pushState`/`window.location.hash` instead of using \" + \"router navigation APIs. This can also happen if you are using \" + \"createHashRouter and the user manually changes the URL.\");\n let blockerKey = shouldBlockNavigation({\n currentLocation: state.location,\n nextLocation: location,\n historyAction\n });\n if (blockerKey && delta != null) {\n // Restore the URL to match the current UI, but don't update router state\n let nextHistoryUpdatePromise = new Promise(resolve => {\n unblockBlockerHistoryUpdate = resolve;\n });\n init.history.go(delta * -1);\n // Put the blocker into a blocked state\n updateBlocker(blockerKey, {\n state: \"blocked\",\n location,\n proceed() {\n updateBlocker(blockerKey, {\n state: \"proceeding\",\n proceed: undefined,\n reset: undefined,\n location\n });\n // Re-do the same POP navigation we just blocked, after the url\n // restoration is also complete. See:\n // https://github.com/remix-run/react-router/issues/11613\n nextHistoryUpdatePromise.then(() => init.history.go(delta));\n },\n reset() {\n let blockers = new Map(state.blockers);\n blockers.set(blockerKey, IDLE_BLOCKER);\n updateState({\n blockers\n });\n }\n });\n return;\n }\n return startNavigation(historyAction, location);\n });\n if (isBrowser) {\n // FIXME: This feels gross. How can we cleanup the lines between\n // scrollRestoration/appliedTransitions persistance?\n restoreAppliedTransitions(routerWindow, appliedViewTransitions);\n let _saveAppliedTransitions = () => persistAppliedTransitions(routerWindow, appliedViewTransitions);\n routerWindow.addEventListener(\"pagehide\", _saveAppliedTransitions);\n removePageHideEventListener = () => routerWindow.removeEventListener(\"pagehide\", _saveAppliedTransitions);\n }\n // Kick off initial data load if needed. Use Pop to avoid modifying history\n // Note we don't do any handling of lazy here. For SPA's it'll get handled\n // in the normal navigation flow. For SSR it's expected that lazy modules are\n // resolved prior to router creation since we can't go into a fallbackElement\n // UI for SSR'd apps\n if (!state.initialized) {\n startNavigation(Action.Pop, state.location, {\n initialHydration: true\n });\n }\n return router;\n }\n // Clean up a router and it's side effects\n function dispose() {\n if (unlistenHistory) {\n unlistenHistory();\n }\n if (removePageHideEventListener) {\n removePageHideEventListener();\n }\n subscribers.clear();\n pendingNavigationController && pendingNavigationController.abort();\n state.fetchers.forEach((_, key) => deleteFetcher(key));\n state.blockers.forEach((_, key) => deleteBlocker(key));\n }\n // Subscribe to state updates for the router\n function subscribe(fn) {\n subscribers.add(fn);\n return () => subscribers.delete(fn);\n }\n // Update our state and notify the calling context of the change\n function updateState(newState, opts) {\n if (opts === void 0) {\n opts = {};\n }\n state = _extends({}, state, newState);\n // Prep fetcher cleanup so we can tell the UI which fetcher data entries\n // can be removed\n let completedFetchers = [];\n let deletedFetchersKeys = [];\n if (future.v7_fetcherPersist) {\n state.fetchers.forEach((fetcher, key) => {\n if (fetcher.state === \"idle\") {\n if (deletedFetchers.has(key)) {\n // Unmounted from the UI and can be totally removed\n deletedFetchersKeys.push(key);\n } else {\n // Returned to idle but still mounted in the UI, so semi-remains for\n // revalidations and such\n completedFetchers.push(key);\n }\n }\n });\n }\n // Iterate over a local copy so that if flushSync is used and we end up\n // removing and adding a new subscriber due to the useCallback dependencies,\n // we don't get ourselves into a loop calling the new subscriber immediately\n [...subscribers].forEach(subscriber => subscriber(state, {\n deletedFetchers: deletedFetchersKeys,\n unstable_viewTransitionOpts: opts.viewTransitionOpts,\n unstable_flushSync: opts.flushSync === true\n }));\n // Remove idle fetchers from state since we only care about in-flight fetchers.\n if (future.v7_fetcherPersist) {\n completedFetchers.forEach(key => state.fetchers.delete(key));\n deletedFetchersKeys.forEach(key => deleteFetcher(key));\n }\n }\n // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION\n // and setting state.[historyAction/location/matches] to the new route.\n // - Location is a required param\n // - Navigation will always be set to IDLE_NAVIGATION\n // - Can pass any other state in newState\n function completeNavigation(location, newState, _temp) {\n var _location$state, _location$state2;\n let {\n flushSync\n } = _temp === void 0 ? {} : _temp;\n // Deduce if we're in a loading/actionReload state:\n // - We have committed actionData in the store\n // - The current navigation was a mutation submission\n // - We're past the submitting state and into the loading state\n // - The location being loaded is not the result of a redirect\n let isActionReload = state.actionData != null && state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && state.navigation.state === \"loading\" && ((_location$state = location.state) == null ? void 0 : _location$state._isRedirect) !== true;\n let actionData;\n if (newState.actionData) {\n if (Object.keys(newState.actionData).length > 0) {\n actionData = newState.actionData;\n } else {\n // Empty actionData -> clear prior actionData due to an action error\n actionData = null;\n }\n } else if (isActionReload) {\n // Keep the current data if we're wrapping up the action reload\n actionData = state.actionData;\n } else {\n // Clear actionData on any other completed navigations\n actionData = null;\n }\n // Always preserve any existing loaderData from re-used routes\n let loaderData = newState.loaderData ? mergeLoaderData(state.loaderData, newState.loaderData, newState.matches || [], newState.errors) : state.loaderData;\n // On a successful navigation we can assume we got through all blockers\n // so we can start fresh\n let blockers = state.blockers;\n if (blockers.size > 0) {\n blockers = new Map(blockers);\n blockers.forEach((_, k) => blockers.set(k, IDLE_BLOCKER));\n }\n // Always respect the user flag. Otherwise don't reset on mutation\n // submission navigations unless they redirect\n let preventScrollReset = pendingPreventScrollReset === true || state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && ((_location$state2 = location.state) == null ? void 0 : _location$state2._isRedirect) !== true;\n // Commit any in-flight routes at the end of the HMR revalidation \"navigation\"\n if (inFlightDataRoutes) {\n dataRoutes = inFlightDataRoutes;\n inFlightDataRoutes = undefined;\n }\n if (isUninterruptedRevalidation) ; else if (pendingAction === Action.Pop) ; else if (pendingAction === Action.Push) {\n init.history.push(location, location.state);\n } else if (pendingAction === Action.Replace) {\n init.history.replace(location, location.state);\n }\n let viewTransitionOpts;\n // On POP, enable transitions if they were enabled on the original navigation\n if (pendingAction === Action.Pop) {\n // Forward takes precedence so they behave like the original navigation\n let priorPaths = appliedViewTransitions.get(state.location.pathname);\n if (priorPaths && priorPaths.has(location.pathname)) {\n viewTransitionOpts = {\n currentLocation: state.location,\n nextLocation: location\n };\n } else if (appliedViewTransitions.has(location.pathname)) {\n // If we don't have a previous forward nav, assume we're popping back to\n // the new location and enable if that location previously enabled\n viewTransitionOpts = {\n currentLocation: location,\n nextLocation: state.location\n };\n }\n } else if (pendingViewTransitionEnabled) {\n // Store the applied transition on PUSH/REPLACE\n let toPaths = appliedViewTransitions.get(state.location.pathname);\n if (toPaths) {\n toPaths.add(location.pathname);\n } else {\n toPaths = new Set([location.pathname]);\n appliedViewTransitions.set(state.location.pathname, toPaths);\n }\n viewTransitionOpts = {\n currentLocation: state.location,\n nextLocation: location\n };\n }\n updateState(_extends({}, newState, {\n actionData,\n loaderData,\n historyAction: pendingAction,\n location,\n initialized: true,\n navigation: IDLE_NAVIGATION,\n revalidation: \"idle\",\n restoreScrollPosition: getSavedScrollPosition(location, newState.matches || state.matches),\n preventScrollReset,\n blockers\n }), {\n viewTransitionOpts,\n flushSync: flushSync === true\n });\n // Reset stateful navigation vars\n pendingAction = Action.Pop;\n pendingPreventScrollReset = false;\n pendingViewTransitionEnabled = false;\n isUninterruptedRevalidation = false;\n isRevalidationRequired = false;\n cancelledDeferredRoutes = [];\n }\n // Trigger a navigation event, which can either be a numerical POP or a PUSH\n // replace with an optional submission\n async function navigate(to, opts) {\n if (typeof to === \"number\") {\n init.history.go(to);\n return;\n }\n let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, to, future.v7_relativeSplatPath, opts == null ? void 0 : opts.fromRouteId, opts == null ? void 0 : opts.relative);\n let {\n path,\n submission,\n error\n } = normalizeNavigateOptions(future.v7_normalizeFormMethod, false, normalizedPath, opts);\n let currentLocation = state.location;\n let nextLocation = createLocation(state.location, path, opts && opts.state);\n // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded\n // URL from window.location, so we need to encode it here so the behavior\n // remains the same as POP and non-data-router usages. new URL() does all\n // the same encoding we'd get from a history.pushState/window.location read\n // without having to touch history\n nextLocation = _extends({}, nextLocation, init.history.encodeLocation(nextLocation));\n let userReplace = opts && opts.replace != null ? opts.replace : undefined;\n let historyAction = Action.Push;\n if (userReplace === true) {\n historyAction = Action.Replace;\n } else if (userReplace === false) ; else if (submission != null && isMutationMethod(submission.formMethod) && submission.formAction === state.location.pathname + state.location.search) {\n // By default on submissions to the current location we REPLACE so that\n // users don't have to double-click the back button to get to the prior\n // location. If the user redirects to a different location from the\n // action/loader this will be ignored and the redirect will be a PUSH\n historyAction = Action.Replace;\n }\n let preventScrollReset = opts && \"preventScrollReset\" in opts ? opts.preventScrollReset === true : undefined;\n let flushSync = (opts && opts.unstable_flushSync) === true;\n let blockerKey = shouldBlockNavigation({\n currentLocation,\n nextLocation,\n historyAction\n });\n if (blockerKey) {\n // Put the blocker into a blocked state\n updateBlocker(blockerKey, {\n state: \"blocked\",\n location: nextLocation,\n proceed() {\n updateBlocker(blockerKey, {\n state: \"proceeding\",\n proceed: undefined,\n reset: undefined,\n location: nextLocation\n });\n // Send the same navigation through\n navigate(to, opts);\n },\n reset() {\n let blockers = new Map(state.blockers);\n blockers.set(blockerKey, IDLE_BLOCKER);\n updateState({\n blockers\n });\n }\n });\n return;\n }\n return await startNavigation(historyAction, nextLocation, {\n submission,\n // Send through the formData serialization error if we have one so we can\n // render at the right error boundary after we match routes\n pendingError: error,\n preventScrollReset,\n replace: opts && opts.replace,\n enableViewTransition: opts && opts.unstable_viewTransition,\n flushSync\n });\n }\n // Revalidate all current loaders. If a navigation is in progress or if this\n // is interrupted by a navigation, allow this to \"succeed\" by calling all\n // loaders during the next loader round\n function revalidate() {\n interruptActiveLoads();\n updateState({\n revalidation: \"loading\"\n });\n // If we're currently submitting an action, we don't need to start a new\n // navigation, we'll just let the follow up loader execution call all loaders\n if (state.navigation.state === \"submitting\") {\n return;\n }\n // If we're currently in an idle state, start a new navigation for the current\n // action/location and mark it as uninterrupted, which will skip the history\n // update in completeNavigation\n if (state.navigation.state === \"idle\") {\n startNavigation(state.historyAction, state.location, {\n startUninterruptedRevalidation: true\n });\n return;\n }\n // Otherwise, if we're currently in a loading state, just start a new\n // navigation to the navigation.location but do not trigger an uninterrupted\n // revalidation so that history correctly updates once the navigation completes\n startNavigation(pendingAction || state.historyAction, state.navigation.location, {\n overrideNavigation: state.navigation,\n // Proxy through any rending view transition\n enableViewTransition: pendingViewTransitionEnabled === true\n });\n }\n // Start a navigation to the given action/location. Can optionally provide a\n // overrideNavigation which will override the normalLoad in the case of a redirect\n // navigation\n async function startNavigation(historyAction, location, opts) {\n // Abort any in-progress navigations and start a new one. Unset any ongoing\n // uninterrupted revalidations unless told otherwise, since we want this\n // new navigation to update history normally\n pendingNavigationController && pendingNavigationController.abort();\n pendingNavigationController = null;\n pendingAction = historyAction;\n isUninterruptedRevalidation = (opts && opts.startUninterruptedRevalidation) === true;\n // Save the current scroll position every time we start a new navigation,\n // and track whether we should reset scroll on completion\n saveScrollPosition(state.location, state.matches);\n pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;\n pendingViewTransitionEnabled = (opts && opts.enableViewTransition) === true;\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let loadingNavigation = opts && opts.overrideNavigation;\n let matches = matchRoutes(routesToUse, location, basename);\n let flushSync = (opts && opts.flushSync) === true;\n let fogOfWar = checkFogOfWar(matches, routesToUse, location.pathname);\n if (fogOfWar.active && fogOfWar.matches) {\n matches = fogOfWar.matches;\n }\n // Short circuit with a 404 on the root error boundary if we match nothing\n if (!matches) {\n let {\n error,\n notFoundMatches,\n route\n } = handleNavigational404(location.pathname);\n completeNavigation(location, {\n matches: notFoundMatches,\n loaderData: {},\n errors: {\n [route.id]: error\n }\n }, {\n flushSync\n });\n return;\n }\n // Short circuit if it's only a hash change and not a revalidation or\n // mutation submission.\n //\n // Ignore on initial page loads because since the initial load will always\n // be \"same hash\". For example, on /page#hash and submit a
\n // which will default to a navigation to /page\n if (state.initialized && !isRevalidationRequired && isHashChangeOnly(state.location, location) && !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))) {\n completeNavigation(location, {\n matches\n }, {\n flushSync\n });\n return;\n }\n // Create a controller/Request for this navigation\n pendingNavigationController = new AbortController();\n let request = createClientSideRequest(init.history, location, pendingNavigationController.signal, opts && opts.submission);\n let pendingActionResult;\n if (opts && opts.pendingError) {\n // If we have a pendingError, it means the user attempted a GET submission\n // with binary FormData so assign here and skip to handleLoaders. That\n // way we handle calling loaders above the boundary etc. It's not really\n // different from an actionError in that sense.\n pendingActionResult = [findNearestBoundary(matches).route.id, {\n type: ResultType.error,\n error: opts.pendingError\n }];\n } else if (opts && opts.submission && isMutationMethod(opts.submission.formMethod)) {\n // Call action if we received an action submission\n let actionResult = await handleAction(request, location, opts.submission, matches, fogOfWar.active, {\n replace: opts.replace,\n flushSync\n });\n if (actionResult.shortCircuited) {\n return;\n }\n // If we received a 404 from handleAction, it's because we couldn't lazily\n // discover the destination route so we don't want to call loaders\n if (actionResult.pendingActionResult) {\n let [routeId, result] = actionResult.pendingActionResult;\n if (isErrorResult(result) && isRouteErrorResponse(result.error) && result.error.status === 404) {\n pendingNavigationController = null;\n completeNavigation(location, {\n matches: actionResult.matches,\n loaderData: {},\n errors: {\n [routeId]: result.error\n }\n });\n return;\n }\n }\n matches = actionResult.matches || matches;\n pendingActionResult = actionResult.pendingActionResult;\n loadingNavigation = getLoadingNavigation(location, opts.submission);\n flushSync = false;\n // No need to do fog of war matching again on loader execution\n fogOfWar.active = false;\n // Create a GET request for the loaders\n request = createClientSideRequest(init.history, request.url, request.signal);\n }\n // Call loaders\n let {\n shortCircuited,\n matches: updatedMatches,\n loaderData,\n errors\n } = await handleLoaders(request, location, matches, fogOfWar.active, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, opts && opts.initialHydration === true, flushSync, pendingActionResult);\n if (shortCircuited) {\n return;\n }\n // Clean up now that the action/loaders have completed. Don't clean up if\n // we short circuited because pendingNavigationController will have already\n // been assigned to a new controller for the next navigation\n pendingNavigationController = null;\n completeNavigation(location, _extends({\n matches: updatedMatches || matches\n }, getActionDataForCommit(pendingActionResult), {\n loaderData,\n errors\n }));\n }\n // Call the action matched by the leaf route for this navigation and handle\n // redirects/errors\n async function handleAction(request, location, submission, matches, isFogOfWar, opts) {\n if (opts === void 0) {\n opts = {};\n }\n interruptActiveLoads();\n // Put us in a submitting state\n let navigation = getSubmittingNavigation(location, submission);\n updateState({\n navigation\n }, {\n flushSync: opts.flushSync === true\n });\n if (isFogOfWar) {\n let discoverResult = await discoverRoutes(matches, location.pathname, request.signal);\n if (discoverResult.type === \"aborted\") {\n return {\n shortCircuited: true\n };\n } else if (discoverResult.type === \"error\") {\n let {\n boundaryId,\n error\n } = handleDiscoverRouteError(location.pathname, discoverResult);\n return {\n matches: discoverResult.partialMatches,\n pendingActionResult: [boundaryId, {\n type: ResultType.error,\n error\n }]\n };\n } else if (!discoverResult.matches) {\n let {\n notFoundMatches,\n error,\n route\n } = handleNavigational404(location.pathname);\n return {\n matches: notFoundMatches,\n pendingActionResult: [route.id, {\n type: ResultType.error,\n error\n }]\n };\n } else {\n matches = discoverResult.matches;\n }\n }\n // Call our action and get the result\n let result;\n let actionMatch = getTargetMatch(matches, location);\n if (!actionMatch.route.action && !actionMatch.route.lazy) {\n result = {\n type: ResultType.error,\n error: getInternalRouterError(405, {\n method: request.method,\n pathname: location.pathname,\n routeId: actionMatch.route.id\n })\n };\n } else {\n let results = await callDataStrategy(\"action\", state, request, [actionMatch], matches, null);\n result = results[actionMatch.route.id];\n if (request.signal.aborted) {\n return {\n shortCircuited: true\n };\n }\n }\n if (isRedirectResult(result)) {\n let replace;\n if (opts && opts.replace != null) {\n replace = opts.replace;\n } else {\n // If the user didn't explicity indicate replace behavior, replace if\n // we redirected to the exact same location we're currently at to avoid\n // double back-buttons\n let location = normalizeRedirectLocation(result.response.headers.get(\"Location\"), new URL(request.url), basename);\n replace = location === state.location.pathname + state.location.search;\n }\n await startRedirectNavigation(request, result, true, {\n submission,\n replace\n });\n return {\n shortCircuited: true\n };\n }\n if (isDeferredResult(result)) {\n throw getInternalRouterError(400, {\n type: \"defer-action\"\n });\n }\n if (isErrorResult(result)) {\n // Store off the pending error - we use it to determine which loaders\n // to call and will commit it when we complete the navigation\n let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);\n // By default, all submissions to the current location are REPLACE\n // navigations, but if the action threw an error that'll be rendered in\n // an errorElement, we fall back to PUSH so that the user can use the\n // back button to get back to the pre-submission form location to try\n // again\n if ((opts && opts.replace) !== true) {\n pendingAction = Action.Push;\n }\n return {\n matches,\n pendingActionResult: [boundaryMatch.route.id, result]\n };\n }\n return {\n matches,\n pendingActionResult: [actionMatch.route.id, result]\n };\n }\n // Call all applicable loaders for the given matches, handling redirects,\n // errors, etc.\n async function handleLoaders(request, location, matches, isFogOfWar, overrideNavigation, submission, fetcherSubmission, replace, initialHydration, flushSync, pendingActionResult) {\n // Figure out the right navigation we want to use for data loading\n let loadingNavigation = overrideNavigation || getLoadingNavigation(location, submission);\n // If this was a redirect from an action we don't have a \"submission\" but\n // we have it on the loading navigation so use that if available\n let activeSubmission = submission || fetcherSubmission || getSubmissionFromNavigation(loadingNavigation);\n // If this is an uninterrupted revalidation, we remain in our current idle\n // state. If not, we need to switch to our loading state and load data,\n // preserving any new action data or existing action data (in the case of\n // a revalidation interrupting an actionReload)\n // If we have partialHydration enabled, then don't update the state for the\n // initial data load since it's not a \"navigation\"\n let shouldUpdateNavigationState = !isUninterruptedRevalidation && (!future.v7_partialHydration || !initialHydration);\n // When fog of war is enabled, we enter our `loading` state earlier so we\n // can discover new routes during the `loading` state. We skip this if\n // we've already run actions since we would have done our matching already.\n // If the children() function threw then, we want to proceed with the\n // partial matches it discovered.\n if (isFogOfWar) {\n if (shouldUpdateNavigationState) {\n let actionData = getUpdatedActionData(pendingActionResult);\n updateState(_extends({\n navigation: loadingNavigation\n }, actionData !== undefined ? {\n actionData\n } : {}), {\n flushSync\n });\n }\n let discoverResult = await discoverRoutes(matches, location.pathname, request.signal);\n if (discoverResult.type === \"aborted\") {\n return {\n shortCircuited: true\n };\n } else if (discoverResult.type === \"error\") {\n let {\n boundaryId,\n error\n } = handleDiscoverRouteError(location.pathname, discoverResult);\n return {\n matches: discoverResult.partialMatches,\n loaderData: {},\n errors: {\n [boundaryId]: error\n }\n };\n } else if (!discoverResult.matches) {\n let {\n error,\n notFoundMatches,\n route\n } = handleNavigational404(location.pathname);\n return {\n matches: notFoundMatches,\n loaderData: {},\n errors: {\n [route.id]: error\n }\n };\n } else {\n matches = discoverResult.matches;\n }\n }\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, future.v7_partialHydration && initialHydration === true, future.v7_skipActionErrorRevalidation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionResult);\n // Cancel pending deferreds for no-longer-matched routes or routes we're\n // about to reload. Note that if this is an action reload we would have\n // already cancelled all pending deferreds so this would be a no-op\n cancelActiveDeferreds(routeId => !(matches && matches.some(m => m.route.id === routeId)) || matchesToLoad && matchesToLoad.some(m => m.route.id === routeId));\n pendingNavigationLoadId = ++incrementingLoadId;\n // Short circuit if we have no loaders to run\n if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {\n let updatedFetchers = markFetchRedirectsDone();\n completeNavigation(location, _extends({\n matches,\n loaderData: {},\n // Commit pending error if we're short circuiting\n errors: pendingActionResult && isErrorResult(pendingActionResult[1]) ? {\n [pendingActionResult[0]]: pendingActionResult[1].error\n } : null\n }, getActionDataForCommit(pendingActionResult), updatedFetchers ? {\n fetchers: new Map(state.fetchers)\n } : {}), {\n flushSync\n });\n return {\n shortCircuited: true\n };\n }\n if (shouldUpdateNavigationState) {\n let updates = {};\n if (!isFogOfWar) {\n // Only update navigation/actionNData if we didn't already do it above\n updates.navigation = loadingNavigation;\n let actionData = getUpdatedActionData(pendingActionResult);\n if (actionData !== undefined) {\n updates.actionData = actionData;\n }\n }\n if (revalidatingFetchers.length > 0) {\n updates.fetchers = getUpdatedRevalidatingFetchers(revalidatingFetchers);\n }\n updateState(updates, {\n flushSync\n });\n }\n revalidatingFetchers.forEach(rf => {\n if (fetchControllers.has(rf.key)) {\n abortFetcher(rf.key);\n }\n if (rf.controller) {\n // Fetchers use an independent AbortController so that aborting a fetcher\n // (via deleteFetcher) does not abort the triggering navigation that\n // triggered the revalidation\n fetchControllers.set(rf.key, rf.controller);\n }\n });\n // Proxy navigation abort through to revalidation fetchers\n let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach(f => abortFetcher(f.key));\n if (pendingNavigationController) {\n pendingNavigationController.signal.addEventListener(\"abort\", abortPendingFetchRevalidations);\n }\n let {\n loaderResults,\n fetcherResults\n } = await callLoadersAndMaybeResolveData(state, matches, matchesToLoad, revalidatingFetchers, request);\n if (request.signal.aborted) {\n return {\n shortCircuited: true\n };\n }\n // Clean up _after_ loaders have completed. Don't clean up if we short\n // circuited because fetchControllers would have been aborted and\n // reassigned to new controllers for the next navigation\n if (pendingNavigationController) {\n pendingNavigationController.signal.removeEventListener(\"abort\", abortPendingFetchRevalidations);\n }\n revalidatingFetchers.forEach(rf => fetchControllers.delete(rf.key));\n // If any loaders returned a redirect Response, start a new REPLACE navigation\n let redirect = findRedirect(loaderResults);\n if (redirect) {\n await startRedirectNavigation(request, redirect.result, true, {\n replace\n });\n return {\n shortCircuited: true\n };\n }\n redirect = findRedirect(fetcherResults);\n if (redirect) {\n // If this redirect came from a fetcher make sure we mark it in\n // fetchRedirectIds so it doesn't get revalidated on the next set of\n // loader executions\n fetchRedirectIds.add(redirect.key);\n await startRedirectNavigation(request, redirect.result, true, {\n replace\n });\n return {\n shortCircuited: true\n };\n }\n // Process and commit output from loaders\n let {\n loaderData,\n errors\n } = processLoaderData(state, matches, matchesToLoad, loaderResults, pendingActionResult, revalidatingFetchers, fetcherResults, activeDeferreds);\n // Wire up subscribers to update loaderData as promises settle\n activeDeferreds.forEach((deferredData, routeId) => {\n deferredData.subscribe(aborted => {\n // Note: No need to updateState here since the TrackedPromise on\n // loaderData is stable across resolve/reject\n // Remove this instance if we were aborted or if promises have settled\n if (aborted || deferredData.done) {\n activeDeferreds.delete(routeId);\n }\n });\n });\n // During partial hydration, preserve SSR errors for routes that don't re-run\n if (future.v7_partialHydration && initialHydration && state.errors) {\n Object.entries(state.errors).filter(_ref2 => {\n let [id] = _ref2;\n return !matchesToLoad.some(m => m.route.id === id);\n }).forEach(_ref3 => {\n let [routeId, error] = _ref3;\n errors = Object.assign(errors || {}, {\n [routeId]: error\n });\n });\n }\n let updatedFetchers = markFetchRedirectsDone();\n let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);\n let shouldUpdateFetchers = updatedFetchers || didAbortFetchLoads || revalidatingFetchers.length > 0;\n return _extends({\n matches,\n loaderData,\n errors\n }, shouldUpdateFetchers ? {\n fetchers: new Map(state.fetchers)\n } : {});\n }\n function getUpdatedActionData(pendingActionResult) {\n if (pendingActionResult && !isErrorResult(pendingActionResult[1])) {\n // This is cast to `any` currently because `RouteData`uses any and it\n // would be a breaking change to use any.\n // TODO: v7 - change `RouteData` to use `unknown` instead of `any`\n return {\n [pendingActionResult[0]]: pendingActionResult[1].data\n };\n } else if (state.actionData) {\n if (Object.keys(state.actionData).length === 0) {\n return null;\n } else {\n return state.actionData;\n }\n }\n }\n function getUpdatedRevalidatingFetchers(revalidatingFetchers) {\n revalidatingFetchers.forEach(rf => {\n let fetcher = state.fetchers.get(rf.key);\n let revalidatingFetcher = getLoadingFetcher(undefined, fetcher ? fetcher.data : undefined);\n state.fetchers.set(rf.key, revalidatingFetcher);\n });\n return new Map(state.fetchers);\n }\n // Trigger a fetcher load/submit for the given fetcher key\n function fetch(key, routeId, href, opts) {\n if (isServer) {\n throw new Error(\"router.fetch() was called during the server render, but it shouldn't be. \" + \"You are likely calling a useFetcher() method in the body of your component. \" + \"Try moving it to a useEffect or a callback.\");\n }\n if (fetchControllers.has(key)) abortFetcher(key);\n let flushSync = (opts && opts.unstable_flushSync) === true;\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, href, future.v7_relativeSplatPath, routeId, opts == null ? void 0 : opts.relative);\n let matches = matchRoutes(routesToUse, normalizedPath, basename);\n let fogOfWar = checkFogOfWar(matches, routesToUse, normalizedPath);\n if (fogOfWar.active && fogOfWar.matches) {\n matches = fogOfWar.matches;\n }\n if (!matches) {\n setFetcherError(key, routeId, getInternalRouterError(404, {\n pathname: normalizedPath\n }), {\n flushSync\n });\n return;\n }\n let {\n path,\n submission,\n error\n } = normalizeNavigateOptions(future.v7_normalizeFormMethod, true, normalizedPath, opts);\n if (error) {\n setFetcherError(key, routeId, error, {\n flushSync\n });\n return;\n }\n let match = getTargetMatch(matches, path);\n pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;\n if (submission && isMutationMethod(submission.formMethod)) {\n handleFetcherAction(key, routeId, path, match, matches, fogOfWar.active, flushSync, submission);\n return;\n }\n // Store off the match so we can call it's shouldRevalidate on subsequent\n // revalidations\n fetchLoadMatches.set(key, {\n routeId,\n path\n });\n handleFetcherLoader(key, routeId, path, match, matches, fogOfWar.active, flushSync, submission);\n }\n // Call the action for the matched fetcher.submit(), and then handle redirects,\n // errors, and revalidation\n async function handleFetcherAction(key, routeId, path, match, requestMatches, isFogOfWar, flushSync, submission) {\n interruptActiveLoads();\n fetchLoadMatches.delete(key);\n function detectAndHandle405Error(m) {\n if (!m.route.action && !m.route.lazy) {\n let error = getInternalRouterError(405, {\n method: submission.formMethod,\n pathname: path,\n routeId: routeId\n });\n setFetcherError(key, routeId, error, {\n flushSync\n });\n return true;\n }\n return false;\n }\n if (!isFogOfWar && detectAndHandle405Error(match)) {\n return;\n }\n // Put this fetcher into it's submitting state\n let existingFetcher = state.fetchers.get(key);\n updateFetcherState(key, getSubmittingFetcher(submission, existingFetcher), {\n flushSync\n });\n let abortController = new AbortController();\n let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, submission);\n if (isFogOfWar) {\n let discoverResult = await discoverRoutes(requestMatches, path, fetchRequest.signal);\n if (discoverResult.type === \"aborted\") {\n return;\n } else if (discoverResult.type === \"error\") {\n let {\n error\n } = handleDiscoverRouteError(path, discoverResult);\n setFetcherError(key, routeId, error, {\n flushSync\n });\n return;\n } else if (!discoverResult.matches) {\n setFetcherError(key, routeId, getInternalRouterError(404, {\n pathname: path\n }), {\n flushSync\n });\n return;\n } else {\n requestMatches = discoverResult.matches;\n match = getTargetMatch(requestMatches, path);\n if (detectAndHandle405Error(match)) {\n return;\n }\n }\n }\n // Call the action for the fetcher\n fetchControllers.set(key, abortController);\n let originatingLoadId = incrementingLoadId;\n let actionResults = await callDataStrategy(\"action\", state, fetchRequest, [match], requestMatches, key);\n let actionResult = actionResults[match.route.id];\n if (fetchRequest.signal.aborted) {\n // We can delete this so long as we weren't aborted by our own fetcher\n // re-submit which would have put _new_ controller is in fetchControllers\n if (fetchControllers.get(key) === abortController) {\n fetchControllers.delete(key);\n }\n return;\n }\n // When using v7_fetcherPersist, we don't want errors bubbling up to the UI\n // or redirects processed for unmounted fetchers so we just revert them to\n // idle\n if (future.v7_fetcherPersist && deletedFetchers.has(key)) {\n if (isRedirectResult(actionResult) || isErrorResult(actionResult)) {\n updateFetcherState(key, getDoneFetcher(undefined));\n return;\n }\n // Let SuccessResult's fall through for revalidation\n } else {\n if (isRedirectResult(actionResult)) {\n fetchControllers.delete(key);\n if (pendingNavigationLoadId > originatingLoadId) {\n // A new navigation was kicked off after our action started, so that\n // should take precedence over this redirect navigation. We already\n // set isRevalidationRequired so all loaders for the new route should\n // fire unless opted out via shouldRevalidate\n updateFetcherState(key, getDoneFetcher(undefined));\n return;\n } else {\n fetchRedirectIds.add(key);\n updateFetcherState(key, getLoadingFetcher(submission));\n return startRedirectNavigation(fetchRequest, actionResult, false, {\n fetcherSubmission: submission\n });\n }\n }\n // Process any non-redirect errors thrown\n if (isErrorResult(actionResult)) {\n setFetcherError(key, routeId, actionResult.error);\n return;\n }\n }\n if (isDeferredResult(actionResult)) {\n throw getInternalRouterError(400, {\n type: \"defer-action\"\n });\n }\n // Start the data load for current matches, or the next location if we're\n // in the middle of a navigation\n let nextLocation = state.navigation.location || state.location;\n let revalidationRequest = createClientSideRequest(init.history, nextLocation, abortController.signal);\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let matches = state.navigation.state !== \"idle\" ? matchRoutes(routesToUse, state.navigation.location, basename) : state.matches;\n invariant(matches, \"Didn't find any matches after fetcher action\");\n let loadId = ++incrementingLoadId;\n fetchReloadIds.set(key, loadId);\n let loadFetcher = getLoadingFetcher(submission, actionResult.data);\n state.fetchers.set(key, loadFetcher);\n let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, false, future.v7_skipActionErrorRevalidation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, [match.route.id, actionResult]);\n // Put all revalidating fetchers into the loading state, except for the\n // current fetcher which we want to keep in it's current loading state which\n // contains it's action submission info + action data\n revalidatingFetchers.filter(rf => rf.key !== key).forEach(rf => {\n let staleKey = rf.key;\n let existingFetcher = state.fetchers.get(staleKey);\n let revalidatingFetcher = getLoadingFetcher(undefined, existingFetcher ? existingFetcher.data : undefined);\n state.fetchers.set(staleKey, revalidatingFetcher);\n if (fetchControllers.has(staleKey)) {\n abortFetcher(staleKey);\n }\n if (rf.controller) {\n fetchControllers.set(staleKey, rf.controller);\n }\n });\n updateState({\n fetchers: new Map(state.fetchers)\n });\n let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach(rf => abortFetcher(rf.key));\n abortController.signal.addEventListener(\"abort\", abortPendingFetchRevalidations);\n let {\n loaderResults,\n fetcherResults\n } = await callLoadersAndMaybeResolveData(state, matches, matchesToLoad, revalidatingFetchers, revalidationRequest);\n if (abortController.signal.aborted) {\n return;\n }\n abortController.signal.removeEventListener(\"abort\", abortPendingFetchRevalidations);\n fetchReloadIds.delete(key);\n fetchControllers.delete(key);\n revalidatingFetchers.forEach(r => fetchControllers.delete(r.key));\n let redirect = findRedirect(loaderResults);\n if (redirect) {\n return startRedirectNavigation(revalidationRequest, redirect.result, false);\n }\n redirect = findRedirect(fetcherResults);\n if (redirect) {\n // If this redirect came from a fetcher make sure we mark it in\n // fetchRedirectIds so it doesn't get revalidated on the next set of\n // loader executions\n fetchRedirectIds.add(redirect.key);\n return startRedirectNavigation(revalidationRequest, redirect.result, false);\n }\n // Process and commit output from loaders\n let {\n loaderData,\n errors\n } = processLoaderData(state, matches, matchesToLoad, loaderResults, undefined, revalidatingFetchers, fetcherResults, activeDeferreds);\n // Since we let revalidations complete even if the submitting fetcher was\n // deleted, only put it back to idle if it hasn't been deleted\n if (state.fetchers.has(key)) {\n let doneFetcher = getDoneFetcher(actionResult.data);\n state.fetchers.set(key, doneFetcher);\n }\n abortStaleFetchLoads(loadId);\n // If we are currently in a navigation loading state and this fetcher is\n // more recent than the navigation, we want the newer data so abort the\n // navigation and complete it with the fetcher data\n if (state.navigation.state === \"loading\" && loadId > pendingNavigationLoadId) {\n invariant(pendingAction, \"Expected pending action\");\n pendingNavigationController && pendingNavigationController.abort();\n completeNavigation(state.navigation.location, {\n matches,\n loaderData,\n errors,\n fetchers: new Map(state.fetchers)\n });\n } else {\n // otherwise just update with the fetcher data, preserving any existing\n // loaderData for loaders that did not need to reload. We have to\n // manually merge here since we aren't going through completeNavigation\n updateState({\n errors,\n loaderData: mergeLoaderData(state.loaderData, loaderData, matches, errors),\n fetchers: new Map(state.fetchers)\n });\n isRevalidationRequired = false;\n }\n }\n // Call the matched loader for fetcher.load(), handling redirects, errors, etc.\n async function handleFetcherLoader(key, routeId, path, match, matches, isFogOfWar, flushSync, submission) {\n let existingFetcher = state.fetchers.get(key);\n updateFetcherState(key, getLoadingFetcher(submission, existingFetcher ? existingFetcher.data : undefined), {\n flushSync\n });\n let abortController = new AbortController();\n let fetchRequest = createClientSideRequest(init.history, path, abortController.signal);\n if (isFogOfWar) {\n let discoverResult = await discoverRoutes(matches, path, fetchRequest.signal);\n if (discoverResult.type === \"aborted\") {\n return;\n } else if (discoverResult.type === \"error\") {\n let {\n error\n } = handleDiscoverRouteError(path, discoverResult);\n setFetcherError(key, routeId, error, {\n flushSync\n });\n return;\n } else if (!discoverResult.matches) {\n setFetcherError(key, routeId, getInternalRouterError(404, {\n pathname: path\n }), {\n flushSync\n });\n return;\n } else {\n matches = discoverResult.matches;\n match = getTargetMatch(matches, path);\n }\n }\n // Call the loader for this fetcher route match\n fetchControllers.set(key, abortController);\n let originatingLoadId = incrementingLoadId;\n let results = await callDataStrategy(\"loader\", state, fetchRequest, [match], matches, key);\n let result = results[match.route.id];\n // Deferred isn't supported for fetcher loads, await everything and treat it\n // as a normal load. resolveDeferredData will return undefined if this\n // fetcher gets aborted, so we just leave result untouched and short circuit\n // below if that happens\n if (isDeferredResult(result)) {\n result = (await resolveDeferredData(result, fetchRequest.signal, true)) || result;\n }\n // We can delete this so long as we weren't aborted by our our own fetcher\n // re-load which would have put _new_ controller is in fetchControllers\n if (fetchControllers.get(key) === abortController) {\n fetchControllers.delete(key);\n }\n if (fetchRequest.signal.aborted) {\n return;\n }\n // We don't want errors bubbling up or redirects followed for unmounted\n // fetchers, so short circuit here if it was removed from the UI\n if (deletedFetchers.has(key)) {\n updateFetcherState(key, getDoneFetcher(undefined));\n return;\n }\n // If the loader threw a redirect Response, start a new REPLACE navigation\n if (isRedirectResult(result)) {\n if (pendingNavigationLoadId > originatingLoadId) {\n // A new navigation was kicked off after our loader started, so that\n // should take precedence over this redirect navigation\n updateFetcherState(key, getDoneFetcher(undefined));\n return;\n } else {\n fetchRedirectIds.add(key);\n await startRedirectNavigation(fetchRequest, result, false);\n return;\n }\n }\n // Process any non-redirect errors thrown\n if (isErrorResult(result)) {\n setFetcherError(key, routeId, result.error);\n return;\n }\n invariant(!isDeferredResult(result), \"Unhandled fetcher deferred data\");\n // Put the fetcher back into an idle state\n updateFetcherState(key, getDoneFetcher(result.data));\n }\n /**\n * Utility function to handle redirects returned from an action or loader.\n * Normally, a redirect \"replaces\" the navigation that triggered it. So, for\n * example:\n *\n * - user is on /a\n * - user clicks a link to /b\n * - loader for /b redirects to /c\n *\n * In a non-JS app the browser would track the in-flight navigation to /b and\n * then replace it with /c when it encountered the redirect response. In\n * the end it would only ever update the URL bar with /c.\n *\n * In client-side routing using pushState/replaceState, we aim to emulate\n * this behavior and we also do not update history until the end of the\n * navigation (including processed redirects). This means that we never\n * actually touch history until we've processed redirects, so we just use\n * the history action from the original navigation (PUSH or REPLACE).\n */\n async function startRedirectNavigation(request, redirect, isNavigation, _temp2) {\n let {\n submission,\n fetcherSubmission,\n replace\n } = _temp2 === void 0 ? {} : _temp2;\n if (redirect.response.headers.has(\"X-Remix-Revalidate\")) {\n isRevalidationRequired = true;\n }\n let location = redirect.response.headers.get(\"Location\");\n invariant(location, \"Expected a Location header on the redirect Response\");\n location = normalizeRedirectLocation(location, new URL(request.url), basename);\n let redirectLocation = createLocation(state.location, location, {\n _isRedirect: true\n });\n if (isBrowser) {\n let isDocumentReload = false;\n if (redirect.response.headers.has(\"X-Remix-Reload-Document\")) {\n // Hard reload if the response contained X-Remix-Reload-Document\n isDocumentReload = true;\n } else if (ABSOLUTE_URL_REGEX.test(location)) {\n const url = init.history.createURL(location);\n isDocumentReload =\n // Hard reload if it's an absolute URL to a new origin\n url.origin !== routerWindow.location.origin ||\n // Hard reload if it's an absolute URL that does not match our basename\n stripBasename(url.pathname, basename) == null;\n }\n if (isDocumentReload) {\n if (replace) {\n routerWindow.location.replace(location);\n } else {\n routerWindow.location.assign(location);\n }\n return;\n }\n }\n // There's no need to abort on redirects, since we don't detect the\n // redirect until the action/loaders have settled\n pendingNavigationController = null;\n let redirectHistoryAction = replace === true || redirect.response.headers.has(\"X-Remix-Replace\") ? Action.Replace : Action.Push;\n // Use the incoming submission if provided, fallback on the active one in\n // state.navigation\n let {\n formMethod,\n formAction,\n formEncType\n } = state.navigation;\n if (!submission && !fetcherSubmission && formMethod && formAction && formEncType) {\n submission = getSubmissionFromNavigation(state.navigation);\n }\n // If this was a 307/308 submission we want to preserve the HTTP method and\n // re-submit the GET/POST/PUT/PATCH/DELETE as a submission navigation to the\n // redirected location\n let activeSubmission = submission || fetcherSubmission;\n if (redirectPreserveMethodStatusCodes.has(redirect.response.status) && activeSubmission && isMutationMethod(activeSubmission.formMethod)) {\n await startNavigation(redirectHistoryAction, redirectLocation, {\n submission: _extends({}, activeSubmission, {\n formAction: location\n }),\n // Preserve these flags across redirects\n preventScrollReset: pendingPreventScrollReset,\n enableViewTransition: isNavigation ? pendingViewTransitionEnabled : undefined\n });\n } else {\n // If we have a navigation submission, we will preserve it through the\n // redirect navigation\n let overrideNavigation = getLoadingNavigation(redirectLocation, submission);\n await startNavigation(redirectHistoryAction, redirectLocation, {\n overrideNavigation,\n // Send fetcher submissions through for shouldRevalidate\n fetcherSubmission,\n // Preserve these flags across redirects\n preventScrollReset: pendingPreventScrollReset,\n enableViewTransition: isNavigation ? pendingViewTransitionEnabled : undefined\n });\n }\n }\n // Utility wrapper for calling dataStrategy client-side without having to\n // pass around the manifest, mapRouteProperties, etc.\n async function callDataStrategy(type, state, request, matchesToLoad, matches, fetcherKey) {\n let results;\n let dataResults = {};\n try {\n results = await callDataStrategyImpl(dataStrategyImpl, type, state, request, matchesToLoad, matches, fetcherKey, manifest, mapRouteProperties);\n } catch (e) {\n // If the outer dataStrategy method throws, just return the error for all\n // matches - and it'll naturally bubble to the root\n matchesToLoad.forEach(m => {\n dataResults[m.route.id] = {\n type: ResultType.error,\n error: e\n };\n });\n return dataResults;\n }\n for (let [routeId, result] of Object.entries(results)) {\n if (isRedirectDataStrategyResultResult(result)) {\n let response = result.result;\n dataResults[routeId] = {\n type: ResultType.redirect,\n response: normalizeRelativeRoutingRedirectResponse(response, request, routeId, matches, basename, future.v7_relativeSplatPath)\n };\n } else {\n dataResults[routeId] = await convertDataStrategyResultToDataResult(result);\n }\n }\n return dataResults;\n }\n async function callLoadersAndMaybeResolveData(state, matches, matchesToLoad, fetchersToLoad, request) {\n let currentMatches = state.matches;\n // Kick off loaders and fetchers in parallel\n let loaderResultsPromise = callDataStrategy(\"loader\", state, request, matchesToLoad, matches, null);\n let fetcherResultsPromise = Promise.all(fetchersToLoad.map(async f => {\n if (f.matches && f.match && f.controller) {\n let results = await callDataStrategy(\"loader\", state, createClientSideRequest(init.history, f.path, f.controller.signal), [f.match], f.matches, f.key);\n let result = results[f.match.route.id];\n // Fetcher results are keyed by fetcher key from here on out, not routeId\n return {\n [f.key]: result\n };\n } else {\n return Promise.resolve({\n [f.key]: {\n type: ResultType.error,\n error: getInternalRouterError(404, {\n pathname: f.path\n })\n }\n });\n }\n }));\n let loaderResults = await loaderResultsPromise;\n let fetcherResults = (await fetcherResultsPromise).reduce((acc, r) => Object.assign(acc, r), {});\n await Promise.all([resolveNavigationDeferredResults(matches, loaderResults, request.signal, currentMatches, state.loaderData), resolveFetcherDeferredResults(matches, fetcherResults, fetchersToLoad)]);\n return {\n loaderResults,\n fetcherResults\n };\n }\n function interruptActiveLoads() {\n // Every interruption triggers a revalidation\n isRevalidationRequired = true;\n // Cancel pending route-level deferreds and mark cancelled routes for\n // revalidation\n cancelledDeferredRoutes.push(...cancelActiveDeferreds());\n // Abort in-flight fetcher loads\n fetchLoadMatches.forEach((_, key) => {\n if (fetchControllers.has(key)) {\n cancelledFetcherLoads.add(key);\n abortFetcher(key);\n }\n });\n }\n function updateFetcherState(key, fetcher, opts) {\n if (opts === void 0) {\n opts = {};\n }\n state.fetchers.set(key, fetcher);\n updateState({\n fetchers: new Map(state.fetchers)\n }, {\n flushSync: (opts && opts.flushSync) === true\n });\n }\n function setFetcherError(key, routeId, error, opts) {\n if (opts === void 0) {\n opts = {};\n }\n let boundaryMatch = findNearestBoundary(state.matches, routeId);\n deleteFetcher(key);\n updateState({\n errors: {\n [boundaryMatch.route.id]: error\n },\n fetchers: new Map(state.fetchers)\n }, {\n flushSync: (opts && opts.flushSync) === true\n });\n }\n function getFetcher(key) {\n if (future.v7_fetcherPersist) {\n activeFetchers.set(key, (activeFetchers.get(key) || 0) + 1);\n // If this fetcher was previously marked for deletion, unmark it since we\n // have a new instance\n if (deletedFetchers.has(key)) {\n deletedFetchers.delete(key);\n }\n }\n return state.fetchers.get(key) || IDLE_FETCHER;\n }\n function deleteFetcher(key) {\n let fetcher = state.fetchers.get(key);\n // Don't abort the controller if this is a deletion of a fetcher.submit()\n // in it's loading phase since - we don't want to abort the corresponding\n // revalidation and want them to complete and land\n if (fetchControllers.has(key) && !(fetcher && fetcher.state === \"loading\" && fetchReloadIds.has(key))) {\n abortFetcher(key);\n }\n fetchLoadMatches.delete(key);\n fetchReloadIds.delete(key);\n fetchRedirectIds.delete(key);\n deletedFetchers.delete(key);\n cancelledFetcherLoads.delete(key);\n state.fetchers.delete(key);\n }\n function deleteFetcherAndUpdateState(key) {\n if (future.v7_fetcherPersist) {\n let count = (activeFetchers.get(key) || 0) - 1;\n if (count <= 0) {\n activeFetchers.delete(key);\n deletedFetchers.add(key);\n } else {\n activeFetchers.set(key, count);\n }\n } else {\n deleteFetcher(key);\n }\n updateState({\n fetchers: new Map(state.fetchers)\n });\n }\n function abortFetcher(key) {\n let controller = fetchControllers.get(key);\n invariant(controller, \"Expected fetch controller: \" + key);\n controller.abort();\n fetchControllers.delete(key);\n }\n function markFetchersDone(keys) {\n for (let key of keys) {\n let fetcher = getFetcher(key);\n let doneFetcher = getDoneFetcher(fetcher.data);\n state.fetchers.set(key, doneFetcher);\n }\n }\n function markFetchRedirectsDone() {\n let doneKeys = [];\n let updatedFetchers = false;\n for (let key of fetchRedirectIds) {\n let fetcher = state.fetchers.get(key);\n invariant(fetcher, \"Expected fetcher: \" + key);\n if (fetcher.state === \"loading\") {\n fetchRedirectIds.delete(key);\n doneKeys.push(key);\n updatedFetchers = true;\n }\n }\n markFetchersDone(doneKeys);\n return updatedFetchers;\n }\n function abortStaleFetchLoads(landedId) {\n let yeetedKeys = [];\n for (let [key, id] of fetchReloadIds) {\n if (id < landedId) {\n let fetcher = state.fetchers.get(key);\n invariant(fetcher, \"Expected fetcher: \" + key);\n if (fetcher.state === \"loading\") {\n abortFetcher(key);\n fetchReloadIds.delete(key);\n yeetedKeys.push(key);\n }\n }\n }\n markFetchersDone(yeetedKeys);\n return yeetedKeys.length > 0;\n }\n function getBlocker(key, fn) {\n let blocker = state.blockers.get(key) || IDLE_BLOCKER;\n if (blockerFunctions.get(key) !== fn) {\n blockerFunctions.set(key, fn);\n }\n return blocker;\n }\n function deleteBlocker(key) {\n state.blockers.delete(key);\n blockerFunctions.delete(key);\n }\n // Utility function to update blockers, ensuring valid state transitions\n function updateBlocker(key, newBlocker) {\n let blocker = state.blockers.get(key) || IDLE_BLOCKER;\n // Poor mans state machine :)\n // https://mermaid.live/edit#pako:eNqVkc9OwzAMxl8l8nnjAYrEtDIOHEBIgwvKJTReGy3_lDpIqO27k6awMG0XcrLlnz87nwdonESogKXXBuE79rq75XZO3-yHds0RJVuv70YrPlUrCEe2HfrORS3rubqZfuhtpg5C9wk5tZ4VKcRUq88q9Z8RS0-48cE1iHJkL0ugbHuFLus9L6spZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM\n invariant(blocker.state === \"unblocked\" && newBlocker.state === \"blocked\" || blocker.state === \"blocked\" && newBlocker.state === \"blocked\" || blocker.state === \"blocked\" && newBlocker.state === \"proceeding\" || blocker.state === \"blocked\" && newBlocker.state === \"unblocked\" || blocker.state === \"proceeding\" && newBlocker.state === \"unblocked\", \"Invalid blocker state transition: \" + blocker.state + \" -> \" + newBlocker.state);\n let blockers = new Map(state.blockers);\n blockers.set(key, newBlocker);\n updateState({\n blockers\n });\n }\n function shouldBlockNavigation(_ref4) {\n let {\n currentLocation,\n nextLocation,\n historyAction\n } = _ref4;\n if (blockerFunctions.size === 0) {\n return;\n }\n // We ony support a single active blocker at the moment since we don't have\n // any compelling use cases for multi-blocker yet\n if (blockerFunctions.size > 1) {\n warning(false, \"A router only supports one blocker at a time\");\n }\n let entries = Array.from(blockerFunctions.entries());\n let [blockerKey, blockerFunction] = entries[entries.length - 1];\n let blocker = state.blockers.get(blockerKey);\n if (blocker && blocker.state === \"proceeding\") {\n // If the blocker is currently proceeding, we don't need to re-check\n // it and can let this navigation continue\n return;\n }\n // At this point, we know we're unblocked/blocked so we need to check the\n // user-provided blocker function\n if (blockerFunction({\n currentLocation,\n nextLocation,\n historyAction\n })) {\n return blockerKey;\n }\n }\n function handleNavigational404(pathname) {\n let error = getInternalRouterError(404, {\n pathname\n });\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let {\n matches,\n route\n } = getShortCircuitMatches(routesToUse);\n // Cancel all pending deferred on 404s since we don't keep any routes\n cancelActiveDeferreds();\n return {\n notFoundMatches: matches,\n route,\n error\n };\n }\n function handleDiscoverRouteError(pathname, discoverResult) {\n return {\n boundaryId: findNearestBoundary(discoverResult.partialMatches).route.id,\n error: getInternalRouterError(400, {\n type: \"route-discovery\",\n pathname,\n message: discoverResult.error != null && \"message\" in discoverResult.error ? discoverResult.error : String(discoverResult.error)\n })\n };\n }\n function cancelActiveDeferreds(predicate) {\n let cancelledRouteIds = [];\n activeDeferreds.forEach((dfd, routeId) => {\n if (!predicate || predicate(routeId)) {\n // Cancel the deferred - but do not remove from activeDeferreds here -\n // we rely on the subscribers to do that so our tests can assert proper\n // cleanup via _internalActiveDeferreds\n dfd.cancel();\n cancelledRouteIds.push(routeId);\n activeDeferreds.delete(routeId);\n }\n });\n return cancelledRouteIds;\n }\n // Opt in to capturing and reporting scroll positions during navigations,\n // used by the component\n function enableScrollRestoration(positions, getPosition, getKey) {\n savedScrollPositions = positions;\n getScrollPosition = getPosition;\n getScrollRestorationKey = getKey || null;\n // Perform initial hydration scroll restoration, since we miss the boat on\n // the initial updateState() because we've not yet rendered \n // and therefore have no savedScrollPositions available\n if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) {\n initialScrollRestored = true;\n let y = getSavedScrollPosition(state.location, state.matches);\n if (y != null) {\n updateState({\n restoreScrollPosition: y\n });\n }\n }\n return () => {\n savedScrollPositions = null;\n getScrollPosition = null;\n getScrollRestorationKey = null;\n };\n }\n function getScrollKey(location, matches) {\n if (getScrollRestorationKey) {\n let key = getScrollRestorationKey(location, matches.map(m => convertRouteMatchToUiMatch(m, state.loaderData)));\n return key || location.key;\n }\n return location.key;\n }\n function saveScrollPosition(location, matches) {\n if (savedScrollPositions && getScrollPosition) {\n let key = getScrollKey(location, matches);\n savedScrollPositions[key] = getScrollPosition();\n }\n }\n function getSavedScrollPosition(location, matches) {\n if (savedScrollPositions) {\n let key = getScrollKey(location, matches);\n let y = savedScrollPositions[key];\n if (typeof y === \"number\") {\n return y;\n }\n }\n return null;\n }\n function checkFogOfWar(matches, routesToUse, pathname) {\n if (patchRoutesOnNavigationImpl) {\n // Don't bother re-calling patchRouteOnMiss for a path we've already\n // processed. the last execution would have patched the route tree\n // accordingly so `matches` here are already accurate.\n if (discoveredRoutes.has(pathname)) {\n return {\n active: false,\n matches\n };\n }\n if (!matches) {\n let fogMatches = matchRoutesImpl(routesToUse, pathname, basename, true);\n return {\n active: true,\n matches: fogMatches || []\n };\n } else {\n if (Object.keys(matches[0].params).length > 0) {\n // If we matched a dynamic param or a splat, it might only be because\n // we haven't yet discovered other routes that would match with a\n // higher score. Call patchRoutesOnNavigation just to be sure\n let partialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);\n return {\n active: true,\n matches: partialMatches\n };\n }\n }\n }\n return {\n active: false,\n matches: null\n };\n }\n async function discoverRoutes(matches, pathname, signal) {\n let partialMatches = matches;\n while (true) {\n let isNonHMR = inFlightDataRoutes == null;\n let routesToUse = inFlightDataRoutes || dataRoutes;\n try {\n await loadLazyRouteChildren(patchRoutesOnNavigationImpl, pathname, partialMatches, routesToUse, manifest, mapRouteProperties, pendingPatchRoutes, signal);\n } catch (e) {\n return {\n type: \"error\",\n error: e,\n partialMatches\n };\n } finally {\n // If we are not in the middle of an HMR revalidation and we changed the\n // routes, provide a new identity so when we `updateState` at the end of\n // this navigation/fetch `router.routes` will be a new identity and\n // trigger a re-run of memoized `router.routes` dependencies.\n // HMR will already update the identity and reflow when it lands\n // `inFlightDataRoutes` in `completeNavigation`\n if (isNonHMR) {\n dataRoutes = [...dataRoutes];\n }\n }\n if (signal.aborted) {\n return {\n type: \"aborted\"\n };\n }\n let newMatches = matchRoutes(routesToUse, pathname, basename);\n if (newMatches) {\n addToFifoQueue(pathname, discoveredRoutes);\n return {\n type: \"success\",\n matches: newMatches\n };\n }\n let newPartialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);\n // Avoid loops if the second pass results in the same partial matches\n if (!newPartialMatches || partialMatches.length === newPartialMatches.length && partialMatches.every((m, i) => m.route.id === newPartialMatches[i].route.id)) {\n addToFifoQueue(pathname, discoveredRoutes);\n return {\n type: \"success\",\n matches: null\n };\n }\n partialMatches = newPartialMatches;\n }\n }\n function addToFifoQueue(path, queue) {\n if (queue.size >= discoveredRoutesMaxSize) {\n let first = queue.values().next().value;\n queue.delete(first);\n }\n queue.add(path);\n }\n function _internalSetRoutes(newRoutes) {\n manifest = {};\n inFlightDataRoutes = convertRoutesToDataRoutes(newRoutes, mapRouteProperties, undefined, manifest);\n }\n function patchRoutes(routeId, children) {\n let isNonHMR = inFlightDataRoutes == null;\n let routesToUse = inFlightDataRoutes || dataRoutes;\n patchRoutesImpl(routeId, children, routesToUse, manifest, mapRouteProperties);\n // If we are not in the middle of an HMR revalidation and we changed the\n // routes, provide a new identity and trigger a reflow via `updateState`\n // to re-run memoized `router.routes` dependencies.\n // HMR will already update the identity and reflow when it lands\n // `inFlightDataRoutes` in `completeNavigation`\n if (isNonHMR) {\n dataRoutes = [...dataRoutes];\n updateState({});\n }\n }\n router = {\n get basename() {\n return basename;\n },\n get future() {\n return future;\n },\n get state() {\n return state;\n },\n get routes() {\n return dataRoutes;\n },\n get window() {\n return routerWindow;\n },\n initialize,\n subscribe,\n enableScrollRestoration,\n navigate,\n fetch,\n revalidate,\n // Passthrough to history-aware createHref used by useHref so we get proper\n // hash-aware URLs in DOM paths\n createHref: to => init.history.createHref(to),\n encodeLocation: to => init.history.encodeLocation(to),\n getFetcher,\n deleteFetcher: deleteFetcherAndUpdateState,\n dispose,\n getBlocker,\n deleteBlocker,\n patchRoutes,\n _internalFetchControllers: fetchControllers,\n _internalActiveDeferreds: activeDeferreds,\n // TODO: Remove setRoutes, it's temporary to avoid dealing with\n // updating the tree while validating the update algorithm.\n _internalSetRoutes\n };\n return router;\n}\n//#endregion\n////////////////////////////////////////////////////////////////////////////////\n//#region createStaticHandler\n////////////////////////////////////////////////////////////////////////////////\nconst UNSAFE_DEFERRED_SYMBOL = Symbol(\"deferred\");\nfunction createStaticHandler(routes, opts) {\n invariant(routes.length > 0, \"You must provide a non-empty routes array to createStaticHandler\");\n let manifest = {};\n let basename = (opts ? opts.basename : null) || \"/\";\n let mapRouteProperties;\n if (opts != null && opts.mapRouteProperties) {\n mapRouteProperties = opts.mapRouteProperties;\n } else if (opts != null && opts.detectErrorBoundary) {\n // If they are still using the deprecated version, wrap it with the new API\n let detectErrorBoundary = opts.detectErrorBoundary;\n mapRouteProperties = route => ({\n hasErrorBoundary: detectErrorBoundary(route)\n });\n } else {\n mapRouteProperties = defaultMapRouteProperties;\n }\n // Config driven behavior flags\n let future = _extends({\n v7_relativeSplatPath: false,\n v7_throwAbortReason: false\n }, opts ? opts.future : null);\n let dataRoutes = convertRoutesToDataRoutes(routes, mapRouteProperties, undefined, manifest);\n /**\n * The query() method is intended for document requests, in which we want to\n * call an optional action and potentially multiple loaders for all nested\n * routes. It returns a StaticHandlerContext object, which is very similar\n * to the router state (location, loaderData, actionData, errors, etc.) and\n * also adds SSR-specific information such as the statusCode and headers\n * from action/loaders Responses.\n *\n * It _should_ never throw and should report all errors through the\n * returned context.errors object, properly associating errors to their error\n * boundary. Additionally, it tracks _deepestRenderedBoundaryId which can be\n * used to emulate React error boundaries during SSr by performing a second\n * pass only down to the boundaryId.\n *\n * The one exception where we do not return a StaticHandlerContext is when a\n * redirect response is returned or thrown from any action/loader. We\n * propagate that out and return the raw Response so the HTTP server can\n * return it directly.\n *\n * - `opts.requestContext` is an optional server context that will be passed\n * to actions/loaders in the `context` parameter\n * - `opts.skipLoaderErrorBubbling` is an optional parameter that will prevent\n * the bubbling of errors which allows single-fetch-type implementations\n * where the client will handle the bubbling and we may need to return data\n * for the handling route\n */\n async function query(request, _temp3) {\n let {\n requestContext,\n skipLoaderErrorBubbling,\n unstable_dataStrategy\n } = _temp3 === void 0 ? {} : _temp3;\n let url = new URL(request.url);\n let method = request.method;\n let location = createLocation(\"\", createPath(url), null, \"default\");\n let matches = matchRoutes(dataRoutes, location, basename);\n // SSR supports HEAD requests while SPA doesn't\n if (!isValidMethod(method) && method !== \"HEAD\") {\n let error = getInternalRouterError(405, {\n method\n });\n let {\n matches: methodNotAllowedMatches,\n route\n } = getShortCircuitMatches(dataRoutes);\n return {\n basename,\n location,\n matches: methodNotAllowedMatches,\n loaderData: {},\n actionData: null,\n errors: {\n [route.id]: error\n },\n statusCode: error.status,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null\n };\n } else if (!matches) {\n let error = getInternalRouterError(404, {\n pathname: location.pathname\n });\n let {\n matches: notFoundMatches,\n route\n } = getShortCircuitMatches(dataRoutes);\n return {\n basename,\n location,\n matches: notFoundMatches,\n loaderData: {},\n actionData: null,\n errors: {\n [route.id]: error\n },\n statusCode: error.status,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null\n };\n }\n let result = await queryImpl(request, location, matches, requestContext, unstable_dataStrategy || null, skipLoaderErrorBubbling === true, null);\n if (isResponse(result)) {\n return result;\n }\n // When returning StaticHandlerContext, we patch back in the location here\n // since we need it for React Context. But this helps keep our submit and\n // loadRouteData operating on a Request instead of a Location\n return _extends({\n location,\n basename\n }, result);\n }\n /**\n * The queryRoute() method is intended for targeted route requests, either\n * for fetch ?_data requests or resource route requests. In this case, we\n * are only ever calling a single action or loader, and we are returning the\n * returned value directly. In most cases, this will be a Response returned\n * from the action/loader, but it may be a primitive or other value as well -\n * and in such cases the calling context should handle that accordingly.\n *\n * We do respect the throw/return differentiation, so if an action/loader\n * throws, then this method will throw the value. This is important so we\n * can do proper boundary identification in Remix where a thrown Response\n * must go to the Catch Boundary but a returned Response is happy-path.\n *\n * One thing to note is that any Router-initiated Errors that make sense\n * to associate with a status code will be thrown as an ErrorResponse\n * instance which include the raw Error, such that the calling context can\n * serialize the error as they see fit while including the proper response\n * code. Examples here are 404 and 405 errors that occur prior to reaching\n * any user-defined loaders.\n *\n * - `opts.routeId` allows you to specify the specific route handler to call.\n * If not provided the handler will determine the proper route by matching\n * against `request.url`\n * - `opts.requestContext` is an optional server context that will be passed\n * to actions/loaders in the `context` parameter\n */\n async function queryRoute(request, _temp4) {\n let {\n routeId,\n requestContext,\n unstable_dataStrategy\n } = _temp4 === void 0 ? {} : _temp4;\n let url = new URL(request.url);\n let method = request.method;\n let location = createLocation(\"\", createPath(url), null, \"default\");\n let matches = matchRoutes(dataRoutes, location, basename);\n // SSR supports HEAD requests while SPA doesn't\n if (!isValidMethod(method) && method !== \"HEAD\" && method !== \"OPTIONS\") {\n throw getInternalRouterError(405, {\n method\n });\n } else if (!matches) {\n throw getInternalRouterError(404, {\n pathname: location.pathname\n });\n }\n let match = routeId ? matches.find(m => m.route.id === routeId) : getTargetMatch(matches, location);\n if (routeId && !match) {\n throw getInternalRouterError(403, {\n pathname: location.pathname,\n routeId\n });\n } else if (!match) {\n // This should never hit I don't think?\n throw getInternalRouterError(404, {\n pathname: location.pathname\n });\n }\n let result = await queryImpl(request, location, matches, requestContext, unstable_dataStrategy || null, false, match);\n if (isResponse(result)) {\n return result;\n }\n let error = result.errors ? Object.values(result.errors)[0] : undefined;\n if (error !== undefined) {\n // If we got back result.errors, that means the loader/action threw\n // _something_ that wasn't a Response, but it's not guaranteed/required\n // to be an `instanceof Error` either, so we have to use throw here to\n // preserve the \"error\" state outside of queryImpl.\n throw error;\n }\n // Pick off the right state value to return\n if (result.actionData) {\n return Object.values(result.actionData)[0];\n }\n if (result.loaderData) {\n var _result$activeDeferre;\n let data = Object.values(result.loaderData)[0];\n if ((_result$activeDeferre = result.activeDeferreds) != null && _result$activeDeferre[match.route.id]) {\n data[UNSAFE_DEFERRED_SYMBOL] = result.activeDeferreds[match.route.id];\n }\n return data;\n }\n return undefined;\n }\n async function queryImpl(request, location, matches, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, routeMatch) {\n invariant(request.signal, \"query()/queryRoute() requests must contain an AbortController signal\");\n try {\n if (isMutationMethod(request.method.toLowerCase())) {\n let result = await submit(request, matches, routeMatch || getTargetMatch(matches, location), requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, routeMatch != null);\n return result;\n }\n let result = await loadRouteData(request, matches, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, routeMatch);\n return isResponse(result) ? result : _extends({}, result, {\n actionData: null,\n actionHeaders: {}\n });\n } catch (e) {\n // If the user threw/returned a Response in callLoaderOrAction for a\n // `queryRoute` call, we throw the `DataStrategyResult` to bail out early\n // and then return or throw the raw Response here accordingly\n if (isDataStrategyResult(e) && isResponse(e.result)) {\n if (e.type === ResultType.error) {\n throw e.result;\n }\n return e.result;\n }\n // Redirects are always returned since they don't propagate to catch\n // boundaries\n if (isRedirectResponse(e)) {\n return e;\n }\n throw e;\n }\n }\n async function submit(request, matches, actionMatch, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, isRouteRequest) {\n let result;\n if (!actionMatch.route.action && !actionMatch.route.lazy) {\n let error = getInternalRouterError(405, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: actionMatch.route.id\n });\n if (isRouteRequest) {\n throw error;\n }\n result = {\n type: ResultType.error,\n error\n };\n } else {\n let results = await callDataStrategy(\"action\", request, [actionMatch], matches, isRouteRequest, requestContext, unstable_dataStrategy);\n result = results[actionMatch.route.id];\n if (request.signal.aborted) {\n throwStaticHandlerAbortedError(request, isRouteRequest, future);\n }\n }\n if (isRedirectResult(result)) {\n // Uhhhh - this should never happen, we should always throw these from\n // callLoaderOrAction, but the type narrowing here keeps TS happy and we\n // can get back on the \"throw all redirect responses\" train here should\n // this ever happen :/\n throw new Response(null, {\n status: result.response.status,\n headers: {\n Location: result.response.headers.get(\"Location\")\n }\n });\n }\n if (isDeferredResult(result)) {\n let error = getInternalRouterError(400, {\n type: \"defer-action\"\n });\n if (isRouteRequest) {\n throw error;\n }\n result = {\n type: ResultType.error,\n error\n };\n }\n if (isRouteRequest) {\n // Note: This should only be non-Response values if we get here, since\n // isRouteRequest should throw any Response received in callLoaderOrAction\n if (isErrorResult(result)) {\n throw result.error;\n }\n return {\n matches: [actionMatch],\n loaderData: {},\n actionData: {\n [actionMatch.route.id]: result.data\n },\n errors: null,\n // Note: statusCode + headers are unused here since queryRoute will\n // return the raw Response or value\n statusCode: 200,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null\n };\n }\n // Create a GET request for the loaders\n let loaderRequest = new Request(request.url, {\n headers: request.headers,\n redirect: request.redirect,\n signal: request.signal\n });\n if (isErrorResult(result)) {\n // Store off the pending error - we use it to determine which loaders\n // to call and will commit it when we complete the navigation\n let boundaryMatch = skipLoaderErrorBubbling ? actionMatch : findNearestBoundary(matches, actionMatch.route.id);\n let context = await loadRouteData(loaderRequest, matches, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, null, [boundaryMatch.route.id, result]);\n // action status codes take precedence over loader status codes\n return _extends({}, context, {\n statusCode: isRouteErrorResponse(result.error) ? result.error.status : result.statusCode != null ? result.statusCode : 500,\n actionData: null,\n actionHeaders: _extends({}, result.headers ? {\n [actionMatch.route.id]: result.headers\n } : {})\n });\n }\n let context = await loadRouteData(loaderRequest, matches, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, null);\n return _extends({}, context, {\n actionData: {\n [actionMatch.route.id]: result.data\n }\n }, result.statusCode ? {\n statusCode: result.statusCode\n } : {}, {\n actionHeaders: result.headers ? {\n [actionMatch.route.id]: result.headers\n } : {}\n });\n }\n async function loadRouteData(request, matches, requestContext, unstable_dataStrategy, skipLoaderErrorBubbling, routeMatch, pendingActionResult) {\n let isRouteRequest = routeMatch != null;\n // Short circuit if we have no loaders to run (queryRoute())\n if (isRouteRequest && !(routeMatch != null && routeMatch.route.loader) && !(routeMatch != null && routeMatch.route.lazy)) {\n throw getInternalRouterError(400, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: routeMatch == null ? void 0 : routeMatch.route.id\n });\n }\n let requestMatches = routeMatch ? [routeMatch] : pendingActionResult && isErrorResult(pendingActionResult[1]) ? getLoaderMatchesUntilBoundary(matches, pendingActionResult[0]) : matches;\n let matchesToLoad = requestMatches.filter(m => m.route.loader || m.route.lazy);\n // Short circuit if we have no loaders to run (query())\n if (matchesToLoad.length === 0) {\n return {\n matches,\n // Add a null for all matched routes for proper revalidation on the client\n loaderData: matches.reduce((acc, m) => Object.assign(acc, {\n [m.route.id]: null\n }), {}),\n errors: pendingActionResult && isErrorResult(pendingActionResult[1]) ? {\n [pendingActionResult[0]]: pendingActionResult[1].error\n } : null,\n statusCode: 200,\n loaderHeaders: {},\n activeDeferreds: null\n };\n }\n let results = await callDataStrategy(\"loader\", request, matchesToLoad, matches, isRouteRequest, requestContext, unstable_dataStrategy);\n if (request.signal.aborted) {\n throwStaticHandlerAbortedError(request, isRouteRequest, future);\n }\n // Process and commit output from loaders\n let activeDeferreds = new Map();\n let context = processRouteLoaderData(matches, results, pendingActionResult, activeDeferreds, skipLoaderErrorBubbling);\n // Add a null for any non-loader matches for proper revalidation on the client\n let executedLoaders = new Set(matchesToLoad.map(match => match.route.id));\n matches.forEach(match => {\n if (!executedLoaders.has(match.route.id)) {\n context.loaderData[match.route.id] = null;\n }\n });\n return _extends({}, context, {\n matches,\n activeDeferreds: activeDeferreds.size > 0 ? Object.fromEntries(activeDeferreds.entries()) : null\n });\n }\n // Utility wrapper for calling dataStrategy server-side without having to\n // pass around the manifest, mapRouteProperties, etc.\n async function callDataStrategy(type, request, matchesToLoad, matches, isRouteRequest, requestContext, unstable_dataStrategy) {\n let results = await callDataStrategyImpl(unstable_dataStrategy || defaultDataStrategy, type, null, request, matchesToLoad, matches, null, manifest, mapRouteProperties, requestContext);\n let dataResults = {};\n await Promise.all(matches.map(async match => {\n if (!(match.route.id in results)) {\n return;\n }\n let result = results[match.route.id];\n if (isRedirectDataStrategyResultResult(result)) {\n let response = result.result;\n // Throw redirects and let the server handle them with an HTTP redirect\n throw normalizeRelativeRoutingRedirectResponse(response, request, match.route.id, matches, basename, future.v7_relativeSplatPath);\n }\n if (isResponse(result.result) && isRouteRequest) {\n // For SSR single-route requests, we want to hand Responses back\n // directly without unwrapping\n throw result;\n }\n dataResults[match.route.id] = await convertDataStrategyResultToDataResult(result);\n }));\n return dataResults;\n }\n return {\n dataRoutes,\n query,\n queryRoute\n };\n}\n//#endregion\n////////////////////////////////////////////////////////////////////////////////\n//#region Helpers\n////////////////////////////////////////////////////////////////////////////////\n/**\n * Given an existing StaticHandlerContext and an error thrown at render time,\n * provide an updated StaticHandlerContext suitable for a second SSR render\n */\nfunction getStaticContextFromError(routes, context, error) {\n let newContext = _extends({}, context, {\n statusCode: isRouteErrorResponse(error) ? error.status : 500,\n errors: {\n [context._deepestRenderedBoundaryId || routes[0].id]: error\n }\n });\n return newContext;\n}\nfunction throwStaticHandlerAbortedError(request, isRouteRequest, future) {\n if (future.v7_throwAbortReason && request.signal.reason !== undefined) {\n throw request.signal.reason;\n }\n let method = isRouteRequest ? \"queryRoute\" : \"query\";\n throw new Error(method + \"() call aborted: \" + request.method + \" \" + request.url);\n}\nfunction isSubmissionNavigation(opts) {\n return opts != null && (\"formData\" in opts && opts.formData != null || \"body\" in opts && opts.body !== undefined);\n}\nfunction normalizeTo(location, matches, basename, prependBasename, to, v7_relativeSplatPath, fromRouteId, relative) {\n let contextualMatches;\n let activeRouteMatch;\n if (fromRouteId) {\n // Grab matches up to the calling route so our route-relative logic is\n // relative to the correct source route\n contextualMatches = [];\n for (let match of matches) {\n contextualMatches.push(match);\n if (match.route.id === fromRouteId) {\n activeRouteMatch = match;\n break;\n }\n }\n } else {\n contextualMatches = matches;\n activeRouteMatch = matches[matches.length - 1];\n }\n // Resolve the relative path\n let path = resolveTo(to ? to : \".\", getResolveToMatches(contextualMatches, v7_relativeSplatPath), stripBasename(location.pathname, basename) || location.pathname, relative === \"path\");\n // When `to` is not specified we inherit search/hash from the current\n // location, unlike when to=\".\" and we just inherit the path.\n // See https://github.com/remix-run/remix/issues/927\n if (to == null) {\n path.search = location.search;\n path.hash = location.hash;\n }\n // Add an ?index param for matched index routes if we don't already have one\n if ((to == null || to === \"\" || to === \".\") && activeRouteMatch && activeRouteMatch.route.index && !hasNakedIndexQuery(path.search)) {\n path.search = path.search ? path.search.replace(/^\\?/, \"?index&\") : \"?index\";\n }\n // If we're operating within a basename, prepend it to the pathname. If\n // this is a root navigation, then just use the raw basename which allows\n // the basename to have full control over the presence of a trailing slash\n // on root actions\n if (prependBasename && basename !== \"/\") {\n path.pathname = path.pathname === \"/\" ? basename : joinPaths([basename, path.pathname]);\n }\n return createPath(path);\n}\n// Normalize navigation options by converting formMethod=GET formData objects to\n// URLSearchParams so they behave identically to links with query params\nfunction normalizeNavigateOptions(normalizeFormMethod, isFetcher, path, opts) {\n // Return location verbatim on non-submission navigations\n if (!opts || !isSubmissionNavigation(opts)) {\n return {\n path\n };\n }\n if (opts.formMethod && !isValidMethod(opts.formMethod)) {\n return {\n path,\n error: getInternalRouterError(405, {\n method: opts.formMethod\n })\n };\n }\n let getInvalidBodyError = () => ({\n path,\n error: getInternalRouterError(400, {\n type: \"invalid-body\"\n })\n });\n // Create a Submission on non-GET navigations\n let rawFormMethod = opts.formMethod || \"get\";\n let formMethod = normalizeFormMethod ? rawFormMethod.toUpperCase() : rawFormMethod.toLowerCase();\n let formAction = stripHashFromPath(path);\n if (opts.body !== undefined) {\n if (opts.formEncType === \"text/plain\") {\n // text only support POST/PUT/PATCH/DELETE submissions\n if (!isMutationMethod(formMethod)) {\n return getInvalidBodyError();\n }\n let text = typeof opts.body === \"string\" ? opts.body : opts.body instanceof FormData || opts.body instanceof URLSearchParams ?\n // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#plain-text-form-data\n Array.from(opts.body.entries()).reduce((acc, _ref5) => {\n let [name, value] = _ref5;\n return \"\" + acc + name + \"=\" + value + \"\\n\";\n }, \"\") : String(opts.body);\n return {\n path,\n submission: {\n formMethod,\n formAction,\n formEncType: opts.formEncType,\n formData: undefined,\n json: undefined,\n text\n }\n };\n } else if (opts.formEncType === \"application/json\") {\n // json only supports POST/PUT/PATCH/DELETE submissions\n if (!isMutationMethod(formMethod)) {\n return getInvalidBodyError();\n }\n try {\n let json = typeof opts.body === \"string\" ? JSON.parse(opts.body) : opts.body;\n return {\n path,\n submission: {\n formMethod,\n formAction,\n formEncType: opts.formEncType,\n formData: undefined,\n json,\n text: undefined\n }\n };\n } catch (e) {\n return getInvalidBodyError();\n }\n }\n }\n invariant(typeof FormData === \"function\", \"FormData is not available in this environment\");\n let searchParams;\n let formData;\n if (opts.formData) {\n searchParams = convertFormDataToSearchParams(opts.formData);\n formData = opts.formData;\n } else if (opts.body instanceof FormData) {\n searchParams = convertFormDataToSearchParams(opts.body);\n formData = opts.body;\n } else if (opts.body instanceof URLSearchParams) {\n searchParams = opts.body;\n formData = convertSearchParamsToFormData(searchParams);\n } else if (opts.body == null) {\n searchParams = new URLSearchParams();\n formData = new FormData();\n } else {\n try {\n searchParams = new URLSearchParams(opts.body);\n formData = convertSearchParamsToFormData(searchParams);\n } catch (e) {\n return getInvalidBodyError();\n }\n }\n let submission = {\n formMethod,\n formAction,\n formEncType: opts && opts.formEncType || \"application/x-www-form-urlencoded\",\n formData,\n json: undefined,\n text: undefined\n };\n if (isMutationMethod(submission.formMethod)) {\n return {\n path,\n submission\n };\n }\n // Flatten submission onto URLSearchParams for GET submissions\n let parsedPath = parsePath(path);\n // On GET navigation submissions we can drop the ?index param from the\n // resulting location since all loaders will run. But fetcher GET submissions\n // only run a single loader so we need to preserve any incoming ?index params\n if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) {\n searchParams.append(\"index\", \"\");\n }\n parsedPath.search = \"?\" + searchParams;\n return {\n path: createPath(parsedPath),\n submission\n };\n}\n// Filter out all routes below any caught error as they aren't going to\n// render so we don't need to load them\nfunction getLoaderMatchesUntilBoundary(matches, boundaryId) {\n let boundaryMatches = matches;\n if (boundaryId) {\n let index = matches.findIndex(m => m.route.id === boundaryId);\n if (index >= 0) {\n boundaryMatches = matches.slice(0, index);\n }\n }\n return boundaryMatches;\n}\nfunction getMatchesToLoad(history, state, matches, submission, location, isInitialLoad, skipActionErrorRevalidation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, deletedFetchers, fetchLoadMatches, fetchRedirectIds, routesToUse, basename, pendingActionResult) {\n let actionResult = pendingActionResult ? isErrorResult(pendingActionResult[1]) ? pendingActionResult[1].error : pendingActionResult[1].data : undefined;\n let currentUrl = history.createURL(state.location);\n let nextUrl = history.createURL(location);\n // Pick navigation matches that are net-new or qualify for revalidation\n let boundaryId = pendingActionResult && isErrorResult(pendingActionResult[1]) ? pendingActionResult[0] : undefined;\n let boundaryMatches = boundaryId ? getLoaderMatchesUntilBoundary(matches, boundaryId) : matches;\n // Don't revalidate loaders by default after action 4xx/5xx responses\n // when the flag is enabled. They can still opt-into revalidation via\n // `shouldRevalidate` via `actionResult`\n let actionStatus = pendingActionResult ? pendingActionResult[1].statusCode : undefined;\n let shouldSkipRevalidation = skipActionErrorRevalidation && actionStatus && actionStatus >= 400;\n let navigationMatches = boundaryMatches.filter((match, index) => {\n let {\n route\n } = match;\n if (route.lazy) {\n // We haven't loaded this route yet so we don't know if it's got a loader!\n return true;\n }\n if (route.loader == null) {\n return false;\n }\n if (isInitialLoad) {\n if (typeof route.loader !== \"function\" || route.loader.hydrate) {\n return true;\n }\n return state.loaderData[route.id] === undefined && (\n // Don't re-run if the loader ran and threw an error\n !state.errors || state.errors[route.id] === undefined);\n }\n // Always call the loader on new route instances and pending defer cancellations\n if (isNewLoader(state.loaderData, state.matches[index], match) || cancelledDeferredRoutes.some(id => id === match.route.id)) {\n return true;\n }\n // This is the default implementation for when we revalidate. If the route\n // provides it's own implementation, then we give them full control but\n // provide this value so they can leverage it if needed after they check\n // their own specific use cases\n let currentRouteMatch = state.matches[index];\n let nextRouteMatch = match;\n return shouldRevalidateLoader(match, _extends({\n currentUrl,\n currentParams: currentRouteMatch.params,\n nextUrl,\n nextParams: nextRouteMatch.params\n }, submission, {\n actionResult,\n actionStatus,\n defaultShouldRevalidate: shouldSkipRevalidation ? false :\n // Forced revalidation due to submission, useRevalidator, or X-Remix-Revalidate\n isRevalidationRequired || currentUrl.pathname + currentUrl.search === nextUrl.pathname + nextUrl.search ||\n // Search params affect all loaders\n currentUrl.search !== nextUrl.search || isNewRouteInstance(currentRouteMatch, nextRouteMatch)\n }));\n });\n // Pick fetcher.loads that need to be revalidated\n let revalidatingFetchers = [];\n fetchLoadMatches.forEach((f, key) => {\n // Don't revalidate:\n // - on initial load (shouldn't be any fetchers then anyway)\n // - if fetcher won't be present in the subsequent render\n // - no longer matches the URL (v7_fetcherPersist=false)\n // - was unmounted but persisted due to v7_fetcherPersist=true\n if (isInitialLoad || !matches.some(m => m.route.id === f.routeId) || deletedFetchers.has(key)) {\n return;\n }\n let fetcherMatches = matchRoutes(routesToUse, f.path, basename);\n // If the fetcher path no longer matches, push it in with null matches so\n // we can trigger a 404 in callLoadersAndMaybeResolveData. Note this is\n // currently only a use-case for Remix HMR where the route tree can change\n // at runtime and remove a route previously loaded via a fetcher\n if (!fetcherMatches) {\n revalidatingFetchers.push({\n key,\n routeId: f.routeId,\n path: f.path,\n matches: null,\n match: null,\n controller: null\n });\n return;\n }\n // Revalidating fetchers are decoupled from the route matches since they\n // load from a static href. They revalidate based on explicit revalidation\n // (submission, useRevalidator, or X-Remix-Revalidate)\n let fetcher = state.fetchers.get(key);\n let fetcherMatch = getTargetMatch(fetcherMatches, f.path);\n let shouldRevalidate = false;\n if (fetchRedirectIds.has(key)) {\n // Never trigger a revalidation of an actively redirecting fetcher\n shouldRevalidate = false;\n } else if (cancelledFetcherLoads.has(key)) {\n // Always mark for revalidation if the fetcher was cancelled\n cancelledFetcherLoads.delete(key);\n shouldRevalidate = true;\n } else if (fetcher && fetcher.state !== \"idle\" && fetcher.data === undefined) {\n // If the fetcher hasn't ever completed loading yet, then this isn't a\n // revalidation, it would just be a brand new load if an explicit\n // revalidation is required\n shouldRevalidate = isRevalidationRequired;\n } else {\n // Otherwise fall back on any user-defined shouldRevalidate, defaulting\n // to explicit revalidations only\n shouldRevalidate = shouldRevalidateLoader(fetcherMatch, _extends({\n currentUrl,\n currentParams: state.matches[state.matches.length - 1].params,\n nextUrl,\n nextParams: matches[matches.length - 1].params\n }, submission, {\n actionResult,\n actionStatus,\n defaultShouldRevalidate: shouldSkipRevalidation ? false : isRevalidationRequired\n }));\n }\n if (shouldRevalidate) {\n revalidatingFetchers.push({\n key,\n routeId: f.routeId,\n path: f.path,\n matches: fetcherMatches,\n match: fetcherMatch,\n controller: new AbortController()\n });\n }\n });\n return [navigationMatches, revalidatingFetchers];\n}\nfunction isNewLoader(currentLoaderData, currentMatch, match) {\n let isNew =\n // [a] -> [a, b]\n !currentMatch ||\n // [a, b] -> [a, c]\n match.route.id !== currentMatch.route.id;\n // Handle the case that we don't have data for a re-used route, potentially\n // from a prior error or from a cancelled pending deferred\n let isMissingData = currentLoaderData[match.route.id] === undefined;\n // Always load if this is a net-new route or we don't yet have data\n return isNew || isMissingData;\n}\nfunction isNewRouteInstance(currentMatch, match) {\n let currentPath = currentMatch.route.path;\n return (\n // param change for this match, /users/123 -> /users/456\n currentMatch.pathname !== match.pathname ||\n // splat param changed, which is not present in match.path\n // e.g. /files/images/avatar.jpg -> files/finances.xls\n currentPath != null && currentPath.endsWith(\"*\") && currentMatch.params[\"*\"] !== match.params[\"*\"]\n );\n}\nfunction shouldRevalidateLoader(loaderMatch, arg) {\n if (loaderMatch.route.shouldRevalidate) {\n let routeChoice = loaderMatch.route.shouldRevalidate(arg);\n if (typeof routeChoice === \"boolean\") {\n return routeChoice;\n }\n }\n return arg.defaultShouldRevalidate;\n}\n/**\n * Idempotent utility to execute patchRoutesOnNavigation() to lazily load route\n * definitions and update the routes/routeManifest\n */\nasync function loadLazyRouteChildren(patchRoutesOnNavigationImpl, path, matches, routes, manifest, mapRouteProperties, pendingRouteChildren, signal) {\n let key = [path, ...matches.map(m => m.route.id)].join(\"-\");\n try {\n let pending = pendingRouteChildren.get(key);\n if (!pending) {\n pending = patchRoutesOnNavigationImpl({\n path,\n matches,\n patch: (routeId, children) => {\n if (!signal.aborted) {\n patchRoutesImpl(routeId, children, routes, manifest, mapRouteProperties);\n }\n }\n });\n pendingRouteChildren.set(key, pending);\n }\n if (pending && isPromise(pending)) {\n await pending;\n }\n } finally {\n pendingRouteChildren.delete(key);\n }\n}\nfunction patchRoutesImpl(routeId, children, routesToUse, manifest, mapRouteProperties) {\n if (routeId) {\n var _route$children;\n let route = manifest[routeId];\n invariant(route, \"No route found to patch children into: routeId = \" + routeId);\n let dataChildren = convertRoutesToDataRoutes(children, mapRouteProperties, [routeId, \"patch\", String(((_route$children = route.children) == null ? void 0 : _route$children.length) || \"0\")], manifest);\n if (route.children) {\n route.children.push(...dataChildren);\n } else {\n route.children = dataChildren;\n }\n } else {\n let dataChildren = convertRoutesToDataRoutes(children, mapRouteProperties, [\"patch\", String(routesToUse.length || \"0\")], manifest);\n routesToUse.push(...dataChildren);\n }\n}\n/**\n * Execute route.lazy() methods to lazily load route modules (loader, action,\n * shouldRevalidate) and update the routeManifest in place which shares objects\n * with dataRoutes so those get updated as well.\n */\nasync function loadLazyRouteModule(route, mapRouteProperties, manifest) {\n if (!route.lazy) {\n return;\n }\n let lazyRoute = await route.lazy();\n // If the lazy route function was executed and removed by another parallel\n // call then we can return - first lazy() to finish wins because the return\n // value of lazy is expected to be static\n if (!route.lazy) {\n return;\n }\n let routeToUpdate = manifest[route.id];\n invariant(routeToUpdate, \"No route found in manifest\");\n // Update the route in place. This should be safe because there's no way\n // we could yet be sitting on this route as we can't get there without\n // resolving lazy() first.\n //\n // This is different than the HMR \"update\" use-case where we may actively be\n // on the route being updated. The main concern boils down to \"does this\n // mutation affect any ongoing navigations or any current state.matches\n // values?\". If not, it should be safe to update in place.\n let routeUpdates = {};\n for (let lazyRouteProperty in lazyRoute) {\n let staticRouteValue = routeToUpdate[lazyRouteProperty];\n let isPropertyStaticallyDefined = staticRouteValue !== undefined &&\n // This property isn't static since it should always be updated based\n // on the route updates\n lazyRouteProperty !== \"hasErrorBoundary\";\n warning(!isPropertyStaticallyDefined, \"Route \\\"\" + routeToUpdate.id + \"\\\" has a static property \\\"\" + lazyRouteProperty + \"\\\" \" + \"defined but its lazy function is also returning a value for this property. \" + (\"The lazy route property \\\"\" + lazyRouteProperty + \"\\\" will be ignored.\"));\n if (!isPropertyStaticallyDefined && !immutableRouteKeys.has(lazyRouteProperty)) {\n routeUpdates[lazyRouteProperty] = lazyRoute[lazyRouteProperty];\n }\n }\n // Mutate the route with the provided updates. Do this first so we pass\n // the updated version to mapRouteProperties\n Object.assign(routeToUpdate, routeUpdates);\n // Mutate the `hasErrorBoundary` property on the route based on the route\n // updates and remove the `lazy` function so we don't resolve the lazy\n // route again.\n Object.assign(routeToUpdate, _extends({}, mapRouteProperties(routeToUpdate), {\n lazy: undefined\n }));\n}\n// Default implementation of `dataStrategy` which fetches all loaders in parallel\nasync function defaultDataStrategy(_ref6) {\n let {\n matches\n } = _ref6;\n let matchesToLoad = matches.filter(m => m.shouldLoad);\n let results = await Promise.all(matchesToLoad.map(m => m.resolve()));\n return results.reduce((acc, result, i) => Object.assign(acc, {\n [matchesToLoad[i].route.id]: result\n }), {});\n}\nasync function callDataStrategyImpl(dataStrategyImpl, type, state, request, matchesToLoad, matches, fetcherKey, manifest, mapRouteProperties, requestContext) {\n let loadRouteDefinitionsPromises = matches.map(m => m.route.lazy ? loadLazyRouteModule(m.route, mapRouteProperties, manifest) : undefined);\n let dsMatches = matches.map((match, i) => {\n let loadRoutePromise = loadRouteDefinitionsPromises[i];\n let shouldLoad = matchesToLoad.some(m => m.route.id === match.route.id);\n // `resolve` encapsulates route.lazy(), executing the loader/action,\n // and mapping return values/thrown errors to a `DataStrategyResult`. Users\n // can pass a callback to take fine-grained control over the execution\n // of the loader/action\n let resolve = async handlerOverride => {\n if (handlerOverride && request.method === \"GET\" && (match.route.lazy || match.route.loader)) {\n shouldLoad = true;\n }\n return shouldLoad ? callLoaderOrAction(type, request, match, loadRoutePromise, handlerOverride, requestContext) : Promise.resolve({\n type: ResultType.data,\n result: undefined\n });\n };\n return _extends({}, match, {\n shouldLoad,\n resolve\n });\n });\n // Send all matches here to allow for a middleware-type implementation.\n // handler will be a no-op for unneeded routes and we filter those results\n // back out below.\n let results = await dataStrategyImpl({\n matches: dsMatches,\n request,\n params: matches[0].params,\n fetcherKey,\n context: requestContext\n });\n // Wait for all routes to load here but 'swallow the error since we want\n // it to bubble up from the `await loadRoutePromise` in `callLoaderOrAction` -\n // called from `match.resolve()`\n try {\n await Promise.all(loadRouteDefinitionsPromises);\n } catch (e) {\n // No-op\n }\n return results;\n}\n// Default logic for calling a loader/action is the user has no specified a dataStrategy\nasync function callLoaderOrAction(type, request, match, loadRoutePromise, handlerOverride, staticContext) {\n let result;\n let onReject;\n let runHandler = handler => {\n // Setup a promise we can race against so that abort signals short circuit\n let reject;\n // This will never resolve so safe to type it as Promise to\n // satisfy the function return value\n let abortPromise = new Promise((_, r) => reject = r);\n onReject = () => reject();\n request.signal.addEventListener(\"abort\", onReject);\n let actualHandler = ctx => {\n if (typeof handler !== \"function\") {\n return Promise.reject(new Error(\"You cannot call the handler for a route which defines a boolean \" + (\"\\\"\" + type + \"\\\" [routeId: \" + match.route.id + \"]\")));\n }\n return handler({\n request,\n params: match.params,\n context: staticContext\n }, ...(ctx !== undefined ? [ctx] : []));\n };\n let handlerPromise = (async () => {\n try {\n let val = await (handlerOverride ? handlerOverride(ctx => actualHandler(ctx)) : actualHandler());\n return {\n type: \"data\",\n result: val\n };\n } catch (e) {\n return {\n type: \"error\",\n result: e\n };\n }\n })();\n return Promise.race([handlerPromise, abortPromise]);\n };\n try {\n let handler = match.route[type];\n // If we have a route.lazy promise, await that first\n if (loadRoutePromise) {\n if (handler) {\n // Run statically defined handler in parallel with lazy()\n let handlerError;\n let [value] = await Promise.all([\n // If the handler throws, don't let it immediately bubble out,\n // since we need to let the lazy() execution finish so we know if this\n // route has a boundary that can handle the error\n runHandler(handler).catch(e => {\n handlerError = e;\n }), loadRoutePromise]);\n if (handlerError !== undefined) {\n throw handlerError;\n }\n result = value;\n } else {\n // Load lazy route module, then run any returned handler\n await loadRoutePromise;\n handler = match.route[type];\n if (handler) {\n // Handler still runs even if we got interrupted to maintain consistency\n // with un-abortable behavior of handler execution on non-lazy or\n // previously-lazy-loaded routes\n result = await runHandler(handler);\n } else if (type === \"action\") {\n let url = new URL(request.url);\n let pathname = url.pathname + url.search;\n throw getInternalRouterError(405, {\n method: request.method,\n pathname,\n routeId: match.route.id\n });\n } else {\n // lazy() route has no loader to run. Short circuit here so we don't\n // hit the invariant below that errors on returning undefined.\n return {\n type: ResultType.data,\n result: undefined\n };\n }\n }\n } else if (!handler) {\n let url = new URL(request.url);\n let pathname = url.pathname + url.search;\n throw getInternalRouterError(404, {\n pathname\n });\n } else {\n result = await runHandler(handler);\n }\n invariant(result.result !== undefined, \"You defined \" + (type === \"action\" ? \"an action\" : \"a loader\") + \" for route \" + (\"\\\"\" + match.route.id + \"\\\" but didn't return anything from your `\" + type + \"` \") + \"function. Please return a value or `null`.\");\n } catch (e) {\n // We should already be catching and converting normal handler executions to\n // DataStrategyResults and returning them, so anything that throws here is an\n // unexpected error we still need to wrap\n return {\n type: ResultType.error,\n result: e\n };\n } finally {\n if (onReject) {\n request.signal.removeEventListener(\"abort\", onReject);\n }\n }\n return result;\n}\nasync function convertDataStrategyResultToDataResult(dataStrategyResult) {\n let {\n result,\n type\n } = dataStrategyResult;\n if (isResponse(result)) {\n let data;\n try {\n let contentType = result.headers.get(\"Content-Type\");\n // Check between word boundaries instead of startsWith() due to the last\n // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type\n if (contentType && /\\bapplication\\/json\\b/.test(contentType)) {\n if (result.body == null) {\n data = null;\n } else {\n data = await result.json();\n }\n } else {\n data = await result.text();\n }\n } catch (e) {\n return {\n type: ResultType.error,\n error: e\n };\n }\n if (type === ResultType.error) {\n return {\n type: ResultType.error,\n error: new ErrorResponseImpl(result.status, result.statusText, data),\n statusCode: result.status,\n headers: result.headers\n };\n }\n return {\n type: ResultType.data,\n data,\n statusCode: result.status,\n headers: result.headers\n };\n }\n if (type === ResultType.error) {\n if (isDataWithResponseInit(result)) {\n var _result$init2;\n if (result.data instanceof Error) {\n var _result$init;\n return {\n type: ResultType.error,\n error: result.data,\n statusCode: (_result$init = result.init) == null ? void 0 : _result$init.status\n };\n }\n // Convert thrown unstable_data() to ErrorResponse instances\n result = new ErrorResponseImpl(((_result$init2 = result.init) == null ? void 0 : _result$init2.status) || 500, undefined, result.data);\n }\n return {\n type: ResultType.error,\n error: result,\n statusCode: isRouteErrorResponse(result) ? result.status : undefined\n };\n }\n if (isDeferredData(result)) {\n var _result$init3, _result$init4;\n return {\n type: ResultType.deferred,\n deferredData: result,\n statusCode: (_result$init3 = result.init) == null ? void 0 : _result$init3.status,\n headers: ((_result$init4 = result.init) == null ? void 0 : _result$init4.headers) && new Headers(result.init.headers)\n };\n }\n if (isDataWithResponseInit(result)) {\n var _result$init5, _result$init6;\n return {\n type: ResultType.data,\n data: result.data,\n statusCode: (_result$init5 = result.init) == null ? void 0 : _result$init5.status,\n headers: (_result$init6 = result.init) != null && _result$init6.headers ? new Headers(result.init.headers) : undefined\n };\n }\n return {\n type: ResultType.data,\n data: result\n };\n}\n// Support relative routing in internal redirects\nfunction normalizeRelativeRoutingRedirectResponse(response, request, routeId, matches, basename, v7_relativeSplatPath) {\n let location = response.headers.get(\"Location\");\n invariant(location, \"Redirects returned/thrown from loaders/actions must have a Location header\");\n if (!ABSOLUTE_URL_REGEX.test(location)) {\n let trimmedMatches = matches.slice(0, matches.findIndex(m => m.route.id === routeId) + 1);\n location = normalizeTo(new URL(request.url), trimmedMatches, basename, true, location, v7_relativeSplatPath);\n response.headers.set(\"Location\", location);\n }\n return response;\n}\nfunction normalizeRedirectLocation(location, currentUrl, basename) {\n if (ABSOLUTE_URL_REGEX.test(location)) {\n // Strip off the protocol+origin for same-origin + same-basename absolute redirects\n let normalizedLocation = location;\n let url = normalizedLocation.startsWith(\"//\") ? new URL(currentUrl.protocol + normalizedLocation) : new URL(normalizedLocation);\n let isSameBasename = stripBasename(url.pathname, basename) != null;\n if (url.origin === currentUrl.origin && isSameBasename) {\n return url.pathname + url.search + url.hash;\n }\n }\n return location;\n}\n// Utility method for creating the Request instances for loaders/actions during\n// client-side navigations and fetches. During SSR we will always have a\n// Request instance from the static handler (query/queryRoute)\nfunction createClientSideRequest(history, location, signal, submission) {\n let url = history.createURL(stripHashFromPath(location)).toString();\n let init = {\n signal\n };\n if (submission && isMutationMethod(submission.formMethod)) {\n let {\n formMethod,\n formEncType\n } = submission;\n // Didn't think we needed this but it turns out unlike other methods, patch\n // won't be properly normalized to uppercase and results in a 405 error.\n // See: https://fetch.spec.whatwg.org/#concept-method\n init.method = formMethod.toUpperCase();\n if (formEncType === \"application/json\") {\n init.headers = new Headers({\n \"Content-Type\": formEncType\n });\n init.body = JSON.stringify(submission.json);\n } else if (formEncType === \"text/plain\") {\n // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)\n init.body = submission.text;\n } else if (formEncType === \"application/x-www-form-urlencoded\" && submission.formData) {\n // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)\n init.body = convertFormDataToSearchParams(submission.formData);\n } else {\n // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)\n init.body = submission.formData;\n }\n }\n return new Request(url, init);\n}\nfunction convertFormDataToSearchParams(formData) {\n let searchParams = new URLSearchParams();\n for (let [key, value] of formData.entries()) {\n // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#converting-an-entry-list-to-a-list-of-name-value-pairs\n searchParams.append(key, typeof value === \"string\" ? value : value.name);\n }\n return searchParams;\n}\nfunction convertSearchParamsToFormData(searchParams) {\n let formData = new FormData();\n for (let [key, value] of searchParams.entries()) {\n formData.append(key, value);\n }\n return formData;\n}\nfunction processRouteLoaderData(matches, results, pendingActionResult, activeDeferreds, skipLoaderErrorBubbling) {\n // Fill in loaderData/errors from our loaders\n let loaderData = {};\n let errors = null;\n let statusCode;\n let foundError = false;\n let loaderHeaders = {};\n let pendingError = pendingActionResult && isErrorResult(pendingActionResult[1]) ? pendingActionResult[1].error : undefined;\n // Process loader results into state.loaderData/state.errors\n matches.forEach(match => {\n if (!(match.route.id in results)) {\n return;\n }\n let id = match.route.id;\n let result = results[id];\n invariant(!isRedirectResult(result), \"Cannot handle redirect results in processLoaderData\");\n if (isErrorResult(result)) {\n let error = result.error;\n // If we have a pending action error, we report it at the highest-route\n // that throws a loader error, and then clear it out to indicate that\n // it was consumed\n if (pendingError !== undefined) {\n error = pendingError;\n pendingError = undefined;\n }\n errors = errors || {};\n if (skipLoaderErrorBubbling) {\n errors[id] = error;\n } else {\n // Look upwards from the matched route for the closest ancestor error\n // boundary, defaulting to the root match. Prefer higher error values\n // if lower errors bubble to the same boundary\n let boundaryMatch = findNearestBoundary(matches, id);\n if (errors[boundaryMatch.route.id] == null) {\n errors[boundaryMatch.route.id] = error;\n }\n }\n // Clear our any prior loaderData for the throwing route\n loaderData[id] = undefined;\n // Once we find our first (highest) error, we set the status code and\n // prevent deeper status codes from overriding\n if (!foundError) {\n foundError = true;\n statusCode = isRouteErrorResponse(result.error) ? result.error.status : 500;\n }\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n } else {\n if (isDeferredResult(result)) {\n activeDeferreds.set(id, result.deferredData);\n loaderData[id] = result.deferredData.data;\n // Error status codes always override success status codes, but if all\n // loaders are successful we take the deepest status code.\n if (result.statusCode != null && result.statusCode !== 200 && !foundError) {\n statusCode = result.statusCode;\n }\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n } else {\n loaderData[id] = result.data;\n // Error status codes always override success status codes, but if all\n // loaders are successful we take the deepest status code.\n if (result.statusCode && result.statusCode !== 200 && !foundError) {\n statusCode = result.statusCode;\n }\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n }\n }\n });\n // If we didn't consume the pending action error (i.e., all loaders\n // resolved), then consume it here. Also clear out any loaderData for the\n // throwing route\n if (pendingError !== undefined && pendingActionResult) {\n errors = {\n [pendingActionResult[0]]: pendingError\n };\n loaderData[pendingActionResult[0]] = undefined;\n }\n return {\n loaderData,\n errors,\n statusCode: statusCode || 200,\n loaderHeaders\n };\n}\nfunction processLoaderData(state, matches, matchesToLoad, results, pendingActionResult, revalidatingFetchers, fetcherResults, activeDeferreds) {\n let {\n loaderData,\n errors\n } = processRouteLoaderData(matches, results, pendingActionResult, activeDeferreds, false // This method is only called client side so we always want to bubble\n );\n // Process results from our revalidating fetchers\n revalidatingFetchers.forEach(rf => {\n let {\n key,\n match,\n controller\n } = rf;\n let result = fetcherResults[key];\n invariant(result, \"Did not find corresponding fetcher result\");\n // Process fetcher non-redirect errors\n if (controller && controller.signal.aborted) {\n // Nothing to do for aborted fetchers\n return;\n } else if (isErrorResult(result)) {\n let boundaryMatch = findNearestBoundary(state.matches, match == null ? void 0 : match.route.id);\n if (!(errors && errors[boundaryMatch.route.id])) {\n errors = _extends({}, errors, {\n [boundaryMatch.route.id]: result.error\n });\n }\n state.fetchers.delete(key);\n } else if (isRedirectResult(result)) {\n // Should never get here, redirects should get processed above, but we\n // keep this to type narrow to a success result in the else\n invariant(false, \"Unhandled fetcher revalidation redirect\");\n } else if (isDeferredResult(result)) {\n // Should never get here, deferred data should be awaited for fetchers\n // in resolveDeferredResults\n invariant(false, \"Unhandled fetcher deferred data\");\n } else {\n let doneFetcher = getDoneFetcher(result.data);\n state.fetchers.set(key, doneFetcher);\n }\n });\n return {\n loaderData,\n errors\n };\n}\nfunction mergeLoaderData(loaderData, newLoaderData, matches, errors) {\n let mergedLoaderData = _extends({}, newLoaderData);\n for (let match of matches) {\n let id = match.route.id;\n if (newLoaderData.hasOwnProperty(id)) {\n if (newLoaderData[id] !== undefined) {\n mergedLoaderData[id] = newLoaderData[id];\n }\n } else if (loaderData[id] !== undefined && match.route.loader) {\n // Preserve existing keys not included in newLoaderData and where a loader\n // wasn't removed by HMR\n mergedLoaderData[id] = loaderData[id];\n }\n if (errors && errors.hasOwnProperty(id)) {\n // Don't keep any loader data below the boundary\n break;\n }\n }\n return mergedLoaderData;\n}\nfunction getActionDataForCommit(pendingActionResult) {\n if (!pendingActionResult) {\n return {};\n }\n return isErrorResult(pendingActionResult[1]) ? {\n // Clear out prior actionData on errors\n actionData: {}\n } : {\n actionData: {\n [pendingActionResult[0]]: pendingActionResult[1].data\n }\n };\n}\n// Find the nearest error boundary, looking upwards from the leaf route (or the\n// route specified by routeId) for the closest ancestor error boundary,\n// defaulting to the root match\nfunction findNearestBoundary(matches, routeId) {\n let eligibleMatches = routeId ? matches.slice(0, matches.findIndex(m => m.route.id === routeId) + 1) : [...matches];\n return eligibleMatches.reverse().find(m => m.route.hasErrorBoundary === true) || matches[0];\n}\nfunction getShortCircuitMatches(routes) {\n // Prefer a root layout route if present, otherwise shim in a route object\n let route = routes.length === 1 ? routes[0] : routes.find(r => r.index || !r.path || r.path === \"/\") || {\n id: \"__shim-error-route__\"\n };\n return {\n matches: [{\n params: {},\n pathname: \"\",\n pathnameBase: \"\",\n route\n }],\n route\n };\n}\nfunction getInternalRouterError(status, _temp5) {\n let {\n pathname,\n routeId,\n method,\n type,\n message\n } = _temp5 === void 0 ? {} : _temp5;\n let statusText = \"Unknown Server Error\";\n let errorMessage = \"Unknown @remix-run/router error\";\n if (status === 400) {\n statusText = \"Bad Request\";\n if (type === \"route-discovery\") {\n errorMessage = \"Unable to match URL \\\"\" + pathname + \"\\\" - the `unstable_patchRoutesOnNavigation()` \" + (\"function threw the following error:\\n\" + message);\n } else if (method && pathname && routeId) {\n errorMessage = \"You made a \" + method + \" request to \\\"\" + pathname + \"\\\" but \" + (\"did not provide a `loader` for route \\\"\" + routeId + \"\\\", \") + \"so there is no way to handle the request.\";\n } else if (type === \"defer-action\") {\n errorMessage = \"defer() is not supported in actions\";\n } else if (type === \"invalid-body\") {\n errorMessage = \"Unable to encode submission body\";\n }\n } else if (status === 403) {\n statusText = \"Forbidden\";\n errorMessage = \"Route \\\"\" + routeId + \"\\\" does not match URL \\\"\" + pathname + \"\\\"\";\n } else if (status === 404) {\n statusText = \"Not Found\";\n errorMessage = \"No route matches URL \\\"\" + pathname + \"\\\"\";\n } else if (status === 405) {\n statusText = \"Method Not Allowed\";\n if (method && pathname && routeId) {\n errorMessage = \"You made a \" + method.toUpperCase() + \" request to \\\"\" + pathname + \"\\\" but \" + (\"did not provide an `action` for route \\\"\" + routeId + \"\\\", \") + \"so there is no way to handle the request.\";\n } else if (method) {\n errorMessage = \"Invalid request method \\\"\" + method.toUpperCase() + \"\\\"\";\n }\n }\n return new ErrorResponseImpl(status || 500, statusText, new Error(errorMessage), true);\n}\n// Find any returned redirect errors, starting from the lowest match\nfunction findRedirect(results) {\n let entries = Object.entries(results);\n for (let i = entries.length - 1; i >= 0; i--) {\n let [key, result] = entries[i];\n if (isRedirectResult(result)) {\n return {\n key,\n result\n };\n }\n }\n}\nfunction stripHashFromPath(path) {\n let parsedPath = typeof path === \"string\" ? parsePath(path) : path;\n return createPath(_extends({}, parsedPath, {\n hash: \"\"\n }));\n}\nfunction isHashChangeOnly(a, b) {\n if (a.pathname !== b.pathname || a.search !== b.search) {\n return false;\n }\n if (a.hash === \"\") {\n // /page -> /page#hash\n return b.hash !== \"\";\n } else if (a.hash === b.hash) {\n // /page#hash -> /page#hash\n return true;\n } else if (b.hash !== \"\") {\n // /page#hash -> /page#other\n return true;\n }\n // If the hash is removed the browser will re-perform a request to the server\n // /page#hash -> /page\n return false;\n}\nfunction isPromise(val) {\n return typeof val === \"object\" && val != null && \"then\" in val;\n}\nfunction isDataStrategyResult(result) {\n return result != null && typeof result === \"object\" && \"type\" in result && \"result\" in result && (result.type === ResultType.data || result.type === ResultType.error);\n}\nfunction isRedirectDataStrategyResultResult(result) {\n return isResponse(result.result) && redirectStatusCodes.has(result.result.status);\n}\nfunction isDeferredResult(result) {\n return result.type === ResultType.deferred;\n}\nfunction isErrorResult(result) {\n return result.type === ResultType.error;\n}\nfunction isRedirectResult(result) {\n return (result && result.type) === ResultType.redirect;\n}\nfunction isDataWithResponseInit(value) {\n return typeof value === \"object\" && value != null && \"type\" in value && \"data\" in value && \"init\" in value && value.type === \"DataWithResponseInit\";\n}\nfunction isDeferredData(value) {\n let deferred = value;\n return deferred && typeof deferred === \"object\" && typeof deferred.data === \"object\" && typeof deferred.subscribe === \"function\" && typeof deferred.cancel === \"function\" && typeof deferred.resolveData === \"function\";\n}\nfunction isResponse(value) {\n return value != null && typeof value.status === \"number\" && typeof value.statusText === \"string\" && typeof value.headers === \"object\" && typeof value.body !== \"undefined\";\n}\nfunction isRedirectResponse(result) {\n if (!isResponse(result)) {\n return false;\n }\n let status = result.status;\n let location = result.headers.get(\"Location\");\n return status >= 300 && status <= 399 && location != null;\n}\nfunction isValidMethod(method) {\n return validRequestMethods.has(method.toLowerCase());\n}\nfunction isMutationMethod(method) {\n return validMutationMethods.has(method.toLowerCase());\n}\nasync function resolveNavigationDeferredResults(matches, results, signal, currentMatches, currentLoaderData) {\n let entries = Object.entries(results);\n for (let index = 0; index < entries.length; index++) {\n let [routeId, result] = entries[index];\n let match = matches.find(m => (m == null ? void 0 : m.route.id) === routeId);\n // If we don't have a match, then we can have a deferred result to do\n // anything with. This is for revalidating fetchers where the route was\n // removed during HMR\n if (!match) {\n continue;\n }\n let currentMatch = currentMatches.find(m => m.route.id === match.route.id);\n let isRevalidatingLoader = currentMatch != null && !isNewRouteInstance(currentMatch, match) && (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;\n if (isDeferredResult(result) && isRevalidatingLoader) {\n // Note: we do not have to touch activeDeferreds here since we race them\n // against the signal in resolveDeferredData and they'll get aborted\n // there if needed\n await resolveDeferredData(result, signal, false).then(result => {\n if (result) {\n results[routeId] = result;\n }\n });\n }\n }\n}\nasync function resolveFetcherDeferredResults(matches, results, revalidatingFetchers) {\n for (let index = 0; index < revalidatingFetchers.length; index++) {\n let {\n key,\n routeId,\n controller\n } = revalidatingFetchers[index];\n let result = results[key];\n let match = matches.find(m => (m == null ? void 0 : m.route.id) === routeId);\n // If we don't have a match, then we can have a deferred result to do\n // anything with. This is for revalidating fetchers where the route was\n // removed during HMR\n if (!match) {\n continue;\n }\n if (isDeferredResult(result)) {\n // Note: we do not have to touch activeDeferreds here since we race them\n // against the signal in resolveDeferredData and they'll get aborted\n // there if needed\n invariant(controller, \"Expected an AbortController for revalidating fetcher deferred result\");\n await resolveDeferredData(result, controller.signal, true).then(result => {\n if (result) {\n results[key] = result;\n }\n });\n }\n }\n}\nasync function resolveDeferredData(result, signal, unwrap) {\n if (unwrap === void 0) {\n unwrap = false;\n }\n let aborted = await result.deferredData.resolveData(signal);\n if (aborted) {\n return;\n }\n if (unwrap) {\n try {\n return {\n type: ResultType.data,\n data: result.deferredData.unwrappedData\n };\n } catch (e) {\n // Handle any TrackedPromise._error values encountered while unwrapping\n return {\n type: ResultType.error,\n error: e\n };\n }\n }\n return {\n type: ResultType.data,\n data: result.deferredData.data\n };\n}\nfunction hasNakedIndexQuery(search) {\n return new URLSearchParams(search).getAll(\"index\").some(v => v === \"\");\n}\nfunction getTargetMatch(matches, location) {\n let search = typeof location === \"string\" ? parsePath(location).search : location.search;\n if (matches[matches.length - 1].route.index && hasNakedIndexQuery(search || \"\")) {\n // Return the leaf index route when index is present\n return matches[matches.length - 1];\n }\n // Otherwise grab the deepest \"path contributing\" match (ignoring index and\n // pathless layout routes)\n let pathMatches = getPathContributingMatches(matches);\n return pathMatches[pathMatches.length - 1];\n}\nfunction getSubmissionFromNavigation(navigation) {\n let {\n formMethod,\n formAction,\n formEncType,\n text,\n formData,\n json\n } = navigation;\n if (!formMethod || !formAction || !formEncType) {\n return;\n }\n if (text != null) {\n return {\n formMethod,\n formAction,\n formEncType,\n formData: undefined,\n json: undefined,\n text\n };\n } else if (formData != null) {\n return {\n formMethod,\n formAction,\n formEncType,\n formData,\n json: undefined,\n text: undefined\n };\n } else if (json !== undefined) {\n return {\n formMethod,\n formAction,\n formEncType,\n formData: undefined,\n json,\n text: undefined\n };\n }\n}\nfunction getLoadingNavigation(location, submission) {\n if (submission) {\n let navigation = {\n state: \"loading\",\n location,\n formMethod: submission.formMethod,\n formAction: submission.formAction,\n formEncType: submission.formEncType,\n formData: submission.formData,\n json: submission.json,\n text: submission.text\n };\n return navigation;\n } else {\n let navigation = {\n state: \"loading\",\n location,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n json: undefined,\n text: undefined\n };\n return navigation;\n }\n}\nfunction getSubmittingNavigation(location, submission) {\n let navigation = {\n state: \"submitting\",\n location,\n formMethod: submission.formMethod,\n formAction: submission.formAction,\n formEncType: submission.formEncType,\n formData: submission.formData,\n json: submission.json,\n text: submission.text\n };\n return navigation;\n}\nfunction getLoadingFetcher(submission, data) {\n if (submission) {\n let fetcher = {\n state: \"loading\",\n formMethod: submission.formMethod,\n formAction: submission.formAction,\n formEncType: submission.formEncType,\n formData: submission.formData,\n json: submission.json,\n text: submission.text,\n data\n };\n return fetcher;\n } else {\n let fetcher = {\n state: \"loading\",\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n json: undefined,\n text: undefined,\n data\n };\n return fetcher;\n }\n}\nfunction getSubmittingFetcher(submission, existingFetcher) {\n let fetcher = {\n state: \"submitting\",\n formMethod: submission.formMethod,\n formAction: submission.formAction,\n formEncType: submission.formEncType,\n formData: submission.formData,\n json: submission.json,\n text: submission.text,\n data: existingFetcher ? existingFetcher.data : undefined\n };\n return fetcher;\n}\nfunction getDoneFetcher(data) {\n let fetcher = {\n state: \"idle\",\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n json: undefined,\n text: undefined,\n data\n };\n return fetcher;\n}\nfunction restoreAppliedTransitions(_window, transitions) {\n try {\n let sessionPositions = _window.sessionStorage.getItem(TRANSITIONS_STORAGE_KEY);\n if (sessionPositions) {\n let json = JSON.parse(sessionPositions);\n for (let [k, v] of Object.entries(json || {})) {\n if (v && Array.isArray(v)) {\n transitions.set(k, new Set(v || []));\n }\n }\n }\n } catch (e) {\n // no-op, use default empty object\n }\n}\nfunction persistAppliedTransitions(_window, transitions) {\n if (transitions.size > 0) {\n let json = {};\n for (let [k, v] of transitions) {\n json[k] = [...v];\n }\n try {\n _window.sessionStorage.setItem(TRANSITIONS_STORAGE_KEY, JSON.stringify(json));\n } catch (error) {\n warning(false, \"Failed to save applied view transitions in sessionStorage (\" + error + \").\");\n }\n }\n}\n//#endregion\n\n\n//# sourceMappingURL=router.js.map\n\n\n//# sourceURL=webpack://tududi/./node_modules/@remix-run/router/dist/router.js?"); - -/***/ }), - -/***/ "./node_modules/ansi-html/index.js": -/*!*****************************************!*\ - !*** ./node_modules/ansi-html/index.js ***! - \*****************************************/ -/***/ ((module) => { - -"use strict"; -eval("\n\nmodule.exports = ansiHTML\n\n// Reference to https://github.com/sindresorhus/ansi-regex\nvar _regANSI = /(?:(?:\\u001b\\[)|\\u009b)(?:(?:[0-9]{1,3})?(?:(?:;[0-9]{0,3})*)?[A-M|f-m])|\\u001b[A-M]/\n\nvar _defColors = {\n reset: ['fff', '000'], // [FOREGROUD_COLOR, BACKGROUND_COLOR]\n black: '000',\n red: 'ff0000',\n green: '209805',\n yellow: 'e8bf03',\n blue: '0000ff',\n magenta: 'ff00ff',\n cyan: '00ffee',\n lightgrey: 'f0f0f0',\n darkgrey: '888'\n}\nvar _styles = {\n 30: 'black',\n 31: 'red',\n 32: 'green',\n 33: 'yellow',\n 34: 'blue',\n 35: 'magenta',\n 36: 'cyan',\n 37: 'lightgrey'\n}\nvar _openTags = {\n '1': 'font-weight:bold', // bold\n '2': 'opacity:0.5', // dim\n '3': '', // italic\n '4': '', // underscore\n '8': 'display:none', // hidden\n '9': '' // delete\n}\nvar _closeTags = {\n '23': '', // reset italic\n '24': '', // reset underscore\n '29': '' // reset delete\n}\n\n;[0, 21, 22, 27, 28, 39, 49].forEach(function (n) {\n _closeTags[n] = ''\n})\n\n/**\n * Converts text with ANSI color codes to HTML markup.\n * @param {String} text\n * @returns {*}\n */\nfunction ansiHTML (text) {\n // Returns the text if the string has no ANSI escape code.\n if (!_regANSI.test(text)) {\n return text\n }\n\n // Cache opened sequence.\n var ansiCodes = []\n // Replace with markup.\n var ret = text.replace(/\\033\\[(\\d+)m/g, function (match, seq) {\n var ot = _openTags[seq]\n if (ot) {\n // If current sequence has been opened, close it.\n if (!!~ansiCodes.indexOf(seq)) { // eslint-disable-line no-extra-boolean-cast\n ansiCodes.pop()\n return ''\n }\n // Open tag.\n ansiCodes.push(seq)\n return ot[0] === '<' ? ot : ''\n }\n\n var ct = _closeTags[seq]\n if (ct) {\n // Pop sequence\n ansiCodes.pop()\n return ct\n }\n return ''\n })\n\n // Make sure tags are closed.\n var l = ansiCodes.length\n ;(l > 0) && (ret += Array(l + 1).join(''))\n\n return ret\n}\n\n/**\n * Customize colors.\n * @param {Object} colors reference to _defColors\n */\nansiHTML.setColors = function (colors) {\n if (typeof colors !== 'object') {\n throw new Error('`colors` parameter must be an Object.')\n }\n\n var _finalColors = {}\n for (var key in _defColors) {\n var hex = colors.hasOwnProperty(key) ? colors[key] : null\n if (!hex) {\n _finalColors[key] = _defColors[key]\n continue\n }\n if ('reset' === key) {\n if (typeof hex === 'string') {\n hex = [hex]\n }\n if (!Array.isArray(hex) || hex.length === 0 || hex.some(function (h) {\n return typeof h !== 'string'\n })) {\n throw new Error('The value of `' + key + '` property must be an Array and each item could only be a hex string, e.g.: FF0000')\n }\n var defHexColor = _defColors[key]\n if (!hex[0]) {\n hex[0] = defHexColor[0]\n }\n if (hex.length === 1 || !hex[1]) {\n hex = [hex[0]]\n hex.push(defHexColor[1])\n }\n\n hex = hex.slice(0, 2)\n } else if (typeof hex !== 'string') {\n throw new Error('The value of `' + key + '` property must be a hex string, e.g.: FF0000')\n }\n _finalColors[key] = hex\n }\n _setTags(_finalColors)\n}\n\n/**\n * Reset colors.\n */\nansiHTML.reset = function () {\n _setTags(_defColors)\n}\n\n/**\n * Expose tags, including open and close.\n * @type {Object}\n */\nansiHTML.tags = {}\n\nif (Object.defineProperty) {\n Object.defineProperty(ansiHTML.tags, 'open', {\n get: function () { return _openTags }\n })\n Object.defineProperty(ansiHTML.tags, 'close', {\n get: function () { return _closeTags }\n })\n} else {\n ansiHTML.tags.open = _openTags\n ansiHTML.tags.close = _closeTags\n}\n\nfunction _setTags (colors) {\n // reset all\n _openTags['0'] = 'font-weight:normal;opacity:1;color:#' + colors.reset[0] + ';background:#' + colors.reset[1]\n // inverse\n _openTags['7'] = 'color:#' + colors.reset[1] + ';background:#' + colors.reset[0]\n // dark grey\n _openTags['90'] = 'color:#' + colors.darkgrey\n\n for (var code in _styles) {\n var color = _styles[code]\n var oriColor = colors[color] || '000'\n _openTags[code] = 'color:#' + oriColor\n code = parseInt(code)\n _openTags[(code + 10).toString()] = 'background:#' + oriColor\n }\n}\n\nansiHTML.reset()\n\n\n//# sourceURL=webpack://tududi/./node_modules/ansi-html/index.js?"); - -/***/ }), - -/***/ "./frontend/App.tsx": -/*!**************************!*\ - !*** ./frontend/App.tsx ***! - \**************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router/dist/index.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* harmony import */ var _components_Login__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./components/Login */ \"./frontend/components/Login.tsx\");\n/* harmony import */ var _components_Shared_NotFound__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./components/Shared/NotFound */ \"./frontend/components/Shared/NotFound.tsx\");\n/* harmony import */ var _components_Project_ProjectDetails__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./components/Project/ProjectDetails */ \"./frontend/components/Project/ProjectDetails.tsx\");\n/* harmony import */ var _components_Projects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./components/Projects */ \"./frontend/components/Projects.tsx\");\n/* harmony import */ var _components_Area_AreaDetails__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./components/Area/AreaDetails */ \"./frontend/components/Area/AreaDetails.tsx\");\n/* harmony import */ var _components_Areas__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./components/Areas */ \"./frontend/components/Areas.tsx\");\n/* harmony import */ var _components_Tag_TagDetails__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./components/Tag/TagDetails */ \"./frontend/components/Tag/TagDetails.tsx\");\n/* harmony import */ var _components_Tags__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./components/Tags */ \"./frontend/components/Tags.tsx\");\n/* harmony import */ var _components_Notes__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./components/Notes */ \"./frontend/components/Notes.tsx\");\n/* harmony import */ var _components_Note_NoteDetails__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./components/Note/NoteDetails */ \"./frontend/components/Note/NoteDetails.tsx\");\n/* harmony import */ var _components_Profile_ProfileSettings__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./components/Profile/ProfileSettings */ \"./frontend/components/Profile/ProfileSettings.tsx\");\n/* harmony import */ var _Layout__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./Layout */ \"./frontend/Layout.tsx\");\n/* harmony import */ var _components_Task_TasksToday__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./components/Task/TasksToday */ \"./frontend/components/Task/TasksToday.tsx\");\n/* harmony import */ var _components_Shared_LoadingScreen__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./components/Shared/LoadingScreen */ \"./frontend/components/Shared/LoadingScreen.tsx\");\n/* harmony import */ var _components_Inbox_InboxItems__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./components/Inbox/InboxItems */ \"./frontend/components/Inbox/InboxItems.tsx\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n// Lazy load Tasks component to prevent issues with tags loading\nvar Tasks = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.lazy)(_c = function _c() {\n return __webpack_require__.e(/*! import() */ \"frontend_components_Tasks_tsx\").then(__webpack_require__.bind(__webpack_require__, /*! ./components/Tasks */ \"./frontend/components/Tasks.tsx\"));\n});\n_c2 = Tasks;\nvar App = function App() {\n _s();\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t,\n i18n = _useTranslation.i18n;\n if (!i18n.isInitialized) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Shared_LoadingScreen__WEBPACK_IMPORTED_MODULE_15__[\"default\"], null);\n }\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState2 = _slicedToArray(_useState, 2),\n currentUser = _useState2[0],\n setCurrentUser = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(true),\n _useState4 = _slicedToArray(_useState3, 2),\n loading = _useState4[0],\n setLoading = _useState4[1];\n var fetchCurrentUser = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var response, data;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.prev = 0;\n _context.next = 3;\n return fetch(\"/api/current_user\", {\n credentials: \"include\",\n headers: {\n Accept: \"application/json\"\n }\n });\n case 3:\n response = _context.sent;\n if (response.ok) {\n _context.next = 10;\n break;\n }\n if (!(response.status === 401)) {\n _context.next = 9;\n break;\n }\n console.log(\"User not authenticated, staying on current page\");\n setCurrentUser(null);\n return _context.abrupt(\"return\");\n case 9:\n throw new Error(\"Failed to fetch user: \".concat(response.status));\n case 10:\n _context.next = 12;\n return response.json();\n case 12:\n data = _context.sent;\n if (data.user) {\n setCurrentUser(data.user);\n } else {\n console.log(\"No user data received, staying on current page\");\n setCurrentUser(null);\n }\n _context.next = 20;\n break;\n case 16:\n _context.prev = 16;\n _context.t0 = _context[\"catch\"](0);\n console.error(\"Failed to fetch current user:\", _context.t0);\n setCurrentUser(null);\n case 20:\n _context.prev = 20;\n setLoading(false);\n return _context.finish(20);\n case 23:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[0, 16, 20, 23]]);\n }));\n return function fetchCurrentUser() {\n return _ref.apply(this, arguments);\n };\n }();\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n // Fetch user on mount\n fetchCurrentUser();\n }, []);\n\n // Listen for login events to update user state\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleUserLoggedIn = function handleUserLoggedIn(event) {\n var user = event.detail;\n console.log('User logged in event received:', user);\n setCurrentUser(user);\n };\n window.addEventListener('userLoggedIn', handleUserLoggedIn);\n return function () {\n return window.removeEventListener('userLoggedIn', handleUserLoggedIn);\n };\n }, []);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n if (i18n.isInitialized) {\n fetch(\"/locales/\".concat(i18n.language, \"/translation.json\")).then(function (response) {\n return response.json();\n }).then(function (data) {\n i18n.addResourceBundle(i18n.language, 'translation', data, true, true);\n })[\"catch\"](function (error) {\n console.error(\"Error manually fetching translation file:\", error);\n });\n }\n }, [i18n.isInitialized]);\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(function () {\n var storedPreference = localStorage.getItem(\"isDarkMode\");\n return storedPreference !== null ? storedPreference === \"true\" : window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n }),\n _useState6 = _slicedToArray(_useState5, 2),\n isDarkMode = _useState6[0],\n setIsDarkMode = _useState6[1];\n var toggleDarkMode = function toggleDarkMode() {\n var newValue = !isDarkMode;\n setIsDarkMode(newValue);\n localStorage.setItem(\"isDarkMode\", JSON.stringify(newValue));\n };\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var updateTheme = function updateTheme() {\n document.documentElement.classList.toggle(\"dark\", isDarkMode);\n };\n updateTheme();\n var mediaQuery = window.matchMedia(\"(prefers-color-scheme: dark)\");\n var mediaListener = function mediaListener(e) {\n if (!localStorage.getItem(\"isDarkMode\")) {\n setIsDarkMode(e.matches);\n }\n };\n mediaQuery.addEventListener(\"change\", mediaListener);\n return function () {\n return mediaQuery.removeEventListener(\"change\", mediaListener);\n };\n }, [isDarkMode]);\n var LoadingComponent = function LoadingComponent() {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-center h-screen bg-gray-100 dark:bg-gray-900\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-xl font-semibold text-gray-700 dark:text-gray-200\"\n }, i18n.t('common.loading', 'Loading application... Please wait.')));\n };\n if (loading) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(LoadingComponent, null);\n }\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react__WEBPACK_IMPORTED_MODULE_0__.Suspense, {\n fallback: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(LoadingComponent, null)\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Routes, null, currentUser ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Layout__WEBPACK_IMPORTED_MODULE_13__[\"default\"], {\n currentUser: currentUser,\n setCurrentUser: setCurrentUser,\n isDarkMode: isDarkMode,\n toggleDarkMode: toggleDarkMode\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Outlet, null))\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n index: true,\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Navigate, {\n to: \"/today\",\n replace: true\n })\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n path: \"/today\",\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Task_TasksToday__WEBPACK_IMPORTED_MODULE_14__[\"default\"], null)\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n path: \"/tasks\",\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react__WEBPACK_IMPORTED_MODULE_0__.Suspense, {\n fallback: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"p-4\"\n }, i18n.t('common.loading', 'Loading...'))\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(Tasks, null))\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n path: \"/inbox\",\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Inbox_InboxItems__WEBPACK_IMPORTED_MODULE_16__[\"default\"], null)\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n path: \"/projects\",\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Projects__WEBPACK_IMPORTED_MODULE_5__[\"default\"], null)\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n path: \"/project/:id\",\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Project_ProjectDetails__WEBPACK_IMPORTED_MODULE_4__[\"default\"], null)\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n path: \"/areas\",\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Areas__WEBPACK_IMPORTED_MODULE_7__[\"default\"], null)\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n path: \"/area/:id\",\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Area_AreaDetails__WEBPACK_IMPORTED_MODULE_6__[\"default\"], null)\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n path: \"/tags\",\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Tags__WEBPACK_IMPORTED_MODULE_9__[\"default\"], null)\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n path: \"/tag/:id\",\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Tag_TagDetails__WEBPACK_IMPORTED_MODULE_8__[\"default\"], null)\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n path: \"/notes\",\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Notes__WEBPACK_IMPORTED_MODULE_10__[\"default\"], null)\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n path: \"/note/:id\",\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Note_NoteDetails__WEBPACK_IMPORTED_MODULE_11__[\"default\"], null)\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n path: \"/profile\",\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Profile_ProfileSettings__WEBPACK_IMPORTED_MODULE_12__[\"default\"], {\n currentUser: currentUser,\n isDarkMode: isDarkMode,\n toggleDarkMode: toggleDarkMode\n })\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n path: \"*\",\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Shared_NotFound__WEBPACK_IMPORTED_MODULE_3__[\"default\"], null)\n }))) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n path: \"/login\",\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Login__WEBPACK_IMPORTED_MODULE_2__[\"default\"], null)\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n path: \"/\",\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Navigate, {\n to: \"/login\",\n replace: true\n })\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Route, {\n path: \"*\",\n element: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_17__.Navigate, {\n to: \"/login\",\n replace: true\n })\n }))));\n};\n_s(App, \"7nQiKN5hL2Dy33urFkACBnncSJM=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c3 = App;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (App);\nvar _c, _c2, _c3;\n__webpack_require__.$Refresh$.register(_c, \"Tasks$lazy\");\n__webpack_require__.$Refresh$.register(_c2, \"Tasks\");\n__webpack_require__.$Refresh$.register(_c3, \"App\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/App.tsx?"); - -/***/ }), - -/***/ "./frontend/Layout.tsx": -/*!*****************************!*\ - !*** ./frontend/Layout.tsx ***! - \*****************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* harmony import */ var _components_Navbar__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./components/Navbar */ \"./frontend/components/Navbar.tsx\");\n/* harmony import */ var _components_Sidebar__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./components/Sidebar */ \"./frontend/components/Sidebar.tsx\");\n/* harmony import */ var _styles_tailwind_css__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./styles/tailwind.css */ \"./frontend/styles/tailwind.css\");\n/* harmony import */ var _components_Project_ProjectModal__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./components/Project/ProjectModal */ \"./frontend/components/Project/ProjectModal.tsx\");\n/* harmony import */ var _components_Note_NoteModal__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./components/Note/NoteModal */ \"./frontend/components/Note/NoteModal.tsx\");\n/* harmony import */ var _components_Area_AreaModal__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./components/Area/AreaModal */ \"./frontend/components/Area/AreaModal.tsx\");\n/* harmony import */ var _components_Tag_TagModal__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./components/Tag/TagModal */ \"./frontend/components/Tag/TagModal.tsx\");\n/* harmony import */ var _components_Task_SimplifiedTaskModal__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./components/Task/SimplifiedTaskModal */ \"./frontend/components/Task/SimplifiedTaskModal.tsx\");\n/* harmony import */ var _components_Task_TaskModal__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./components/Task/TaskModal */ \"./frontend/components/Task/TaskModal.tsx\");\n/* harmony import */ var _store_useStore__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./store/useStore */ \"./frontend/store/useStore.ts\");\n/* harmony import */ var _utils_notesService__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./utils/notesService */ \"./frontend/utils/notesService.ts\");\n/* harmony import */ var _utils_areasService__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./utils/areasService */ \"./frontend/utils/areasService.ts\");\n/* harmony import */ var _utils_tagsService__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./utils/tagsService */ \"./frontend/utils/tagsService.ts\");\n/* harmony import */ var _utils_projectsService__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./utils/projectsService */ \"./frontend/utils/projectsService.ts\");\n/* harmony import */ var _utils_tasksService__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./utils/tasksService */ \"./frontend/utils/tasksService.ts\");\n/* harmony import */ var _utils_authUtils__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./utils/authUtils */ \"./frontend/utils/authUtils.ts\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar Layout = function Layout(_ref) {\n _s();\n var currentUser = _ref.currentUser,\n setCurrentUser = _ref.setCurrentUser,\n isDarkMode = _ref.isDarkMode,\n toggleDarkMode = _ref.toggleDarkMode,\n children = _ref.children;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(window.innerWidth >= 1024),\n _useState2 = _slicedToArray(_useState, 2),\n isSidebarOpen = _useState2[0],\n setIsSidebarOpen = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState4 = _slicedToArray(_useState3, 2),\n isTaskModalOpen = _useState4[0],\n setIsTaskModalOpen = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState6 = _slicedToArray(_useState5, 2),\n isProjectModalOpen = _useState6[0],\n setIsProjectModalOpen = _useState6[1];\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState8 = _slicedToArray(_useState7, 2),\n isNoteModalOpen = _useState8[0],\n setIsNoteModalOpen = _useState8[1];\n var _useState9 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState10 = _slicedToArray(_useState9, 2),\n isAreaModalOpen = _useState10[0],\n setIsAreaModalOpen = _useState10[1];\n var _useState11 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState12 = _slicedToArray(_useState11, 2),\n isTagModalOpen = _useState12[0],\n setIsTagModalOpen = _useState12[1];\n var _useState13 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)('simplified'),\n _useState14 = _slicedToArray(_useState13, 2),\n taskModalType = _useState14[0],\n setTaskModalType = _useState14[1];\n var _useState15 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState16 = _slicedToArray(_useState15, 2),\n selectedNote = _useState16[0],\n setSelectedNote = _useState16[1];\n var _useState17 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState18 = _slicedToArray(_useState17, 2),\n selectedArea = _useState18[0],\n setSelectedArea = _useState18[1];\n var _useState19 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState20 = _slicedToArray(_useState19, 2),\n selectedTag = _useState20[0],\n setSelectedTag = _useState20[1];\n var _useState21 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState22 = _slicedToArray(_useState21, 2),\n newTask = _useState22[0],\n setNewTask = _useState22[1];\n var _useStore = (0,_store_useStore__WEBPACK_IMPORTED_MODULE_11__.useStore)(),\n _useStore$notesStore = _useStore.notesStore,\n notes = _useStore$notesStore.notes,\n setNotes = _useStore$notesStore.setNotes,\n setNotesLoading = _useStore$notesStore.setLoading,\n setNotesError = _useStore$notesStore.setError,\n isNotesLoading = _useStore$notesStore.isLoading,\n isNotesError = _useStore$notesStore.isError,\n _useStore$areasStore = _useStore.areasStore,\n areas = _useStore$areasStore.areas,\n setAreas = _useStore$areasStore.setAreas,\n setAreasLoading = _useStore$areasStore.setLoading,\n setAreasError = _useStore$areasStore.setError,\n isAreasLoading = _useStore$areasStore.isLoading,\n isAreasError = _useStore$areasStore.isError,\n _useStore$tasksStore = _useStore.tasksStore,\n setTasksLoading = _useStore$tasksStore.setLoading,\n setTasksError = _useStore$tasksStore.setError,\n isTasksLoading = _useStore$tasksStore.isLoading,\n isTasksError = _useStore$tasksStore.isError,\n _useStore$projectsSto = _useStore.projectsStore,\n projects = _useStore$projectsSto.projects,\n setProjects = _useStore$projectsSto.setProjects,\n setProjectsLoading = _useStore$projectsSto.setLoading,\n setProjectsError = _useStore$projectsSto.setError,\n isProjectsLoading = _useStore$projectsSto.isLoading,\n isProjectsError = _useStore$projectsSto.isError,\n _useStore$tagsStore = _useStore.tagsStore,\n tags = _useStore$tagsStore.tags,\n setTags = _useStore$tagsStore.setTags,\n setTagsLoading = _useStore$tagsStore.setLoading,\n setTagsError = _useStore$tagsStore.setError,\n isTagsLoading = _useStore$tagsStore.isLoading,\n isTagsError = _useStore$tagsStore.isError;\n var openTaskModal = function openTaskModal() {\n var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'simplified';\n setIsTaskModalOpen(true);\n setTaskModalType(type);\n };\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleResize = function handleResize() {\n setIsSidebarOpen(window.innerWidth >= 1024);\n };\n window.addEventListener(\"resize\", handleResize);\n return function () {\n return window.removeEventListener(\"resize\", handleResize);\n };\n }, []);\n var loadNotes = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var notesData;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n setNotesLoading(true);\n _context.prev = 1;\n _context.next = 4;\n return (0,_utils_notesService__WEBPACK_IMPORTED_MODULE_12__.fetchNotes)();\n case 4:\n notesData = _context.sent;\n setNotes(notesData);\n _context.next = 12;\n break;\n case 8:\n _context.prev = 8;\n _context.t0 = _context[\"catch\"](1);\n console.error(\"Error fetching notes:\", _context.t0);\n setNotesError(true);\n case 12:\n _context.prev = 12;\n setNotesLoading(false);\n return _context.finish(12);\n case 15:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[1, 8, 12, 15]]);\n }));\n return function loadNotes() {\n return _ref2.apply(this, arguments);\n };\n }();\n var loadAreas = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {\n var areasData;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n setAreasLoading(true);\n _context2.prev = 1;\n _context2.next = 4;\n return (0,_utils_areasService__WEBPACK_IMPORTED_MODULE_13__.fetchAreas)();\n case 4:\n areasData = _context2.sent;\n setAreas(areasData);\n _context2.next = 12;\n break;\n case 8:\n _context2.prev = 8;\n _context2.t0 = _context2[\"catch\"](1);\n console.error(\"Error fetching areas:\", _context2.t0);\n setAreasError(true);\n case 12:\n _context2.prev = 12;\n setAreasLoading(false);\n return _context2.finish(12);\n case 15:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, null, [[1, 8, 12, 15]]);\n }));\n return function loadAreas() {\n return _ref3.apply(this, arguments);\n };\n }();\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n loadNotes();\n loadAreas();\n }, []);\n var openNoteModal = function openNoteModal() {\n var note = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n setSelectedNote(note);\n setIsNoteModalOpen(true);\n };\n var closeNoteModal = function closeNoteModal() {\n setIsNoteModalOpen(false);\n setSelectedNote(null);\n };\n var closeTaskModal = function closeTaskModal() {\n setIsTaskModalOpen(false);\n setNewTask(null);\n };\n var openProjectModal = function openProjectModal() {\n setIsProjectModalOpen(true);\n };\n var closeProjectModal = function closeProjectModal() {\n setIsProjectModalOpen(false);\n };\n var openAreaModal = function openAreaModal() {\n var area = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n setSelectedArea(area);\n setIsAreaModalOpen(true);\n };\n var closeAreaModal = function closeAreaModal() {\n setIsAreaModalOpen(false);\n setSelectedArea(null);\n };\n var openTagModal = function openTagModal() {\n var tag = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n setSelectedTag(tag);\n setIsTagModalOpen(true);\n };\n var closeTagModal = function closeTagModal() {\n setIsTagModalOpen(false);\n setSelectedTag(null);\n };\n var handleSaveNote = /*#__PURE__*/function () {\n var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(noteData) {\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n _context3.prev = 0;\n if (!noteData.id) {\n _context3.next = 6;\n break;\n }\n _context3.next = 4;\n return (0,_utils_notesService__WEBPACK_IMPORTED_MODULE_12__.updateNote)(noteData.id, noteData);\n case 4:\n _context3.next = 8;\n break;\n case 6:\n _context3.next = 8;\n return (0,_utils_notesService__WEBPACK_IMPORTED_MODULE_12__.createNote)(noteData);\n case 8:\n loadNotes();\n closeNoteModal();\n _context3.next = 18;\n break;\n case 12:\n _context3.prev = 12;\n _context3.t0 = _context3[\"catch\"](0);\n console.error(\"Error saving note:\", _context3.t0);\n // Don't close modal if there's an auth error (user will be redirected)\n if (!(0,_utils_authUtils__WEBPACK_IMPORTED_MODULE_17__.isAuthError)(_context3.t0)) {\n _context3.next = 17;\n break;\n }\n return _context3.abrupt(\"return\");\n case 17:\n closeNoteModal();\n case 18:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3, null, [[0, 12]]);\n }));\n return function handleSaveNote(_x) {\n return _ref4.apply(this, arguments);\n };\n }();\n var handleSaveTask = /*#__PURE__*/function () {\n var _ref5 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4(taskData) {\n return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n while (1) switch (_context4.prev = _context4.next) {\n case 0:\n _context4.prev = 0;\n if (!taskData.id) {\n _context4.next = 6;\n break;\n }\n _context4.next = 4;\n return (0,_utils_tasksService__WEBPACK_IMPORTED_MODULE_16__.updateTask)(taskData.id, taskData);\n case 4:\n _context4.next = 8;\n break;\n case 6:\n _context4.next = 8;\n return (0,_utils_tasksService__WEBPACK_IMPORTED_MODULE_16__.createTask)(taskData);\n case 8:\n // Don't refetch all tasks here - let individual components handle their own state\n // This prevents unnecessary re-renders and race conditions\n closeTaskModal();\n _context4.next = 18;\n break;\n case 11:\n _context4.prev = 11;\n _context4.t0 = _context4[\"catch\"](0);\n console.error(\"Error saving task:\", _context4.t0);\n // Don't close modal if there's an auth error (user will be redirected)\n if (!(0,_utils_authUtils__WEBPACK_IMPORTED_MODULE_17__.isAuthError)(_context4.t0)) {\n _context4.next = 16;\n break;\n }\n return _context4.abrupt(\"return\");\n case 16:\n // For other errors, still close the modal but let the error bubble up\n closeTaskModal();\n throw _context4.t0;\n case 18:\n case \"end\":\n return _context4.stop();\n }\n }, _callee4, null, [[0, 11]]);\n }));\n return function handleSaveTask(_x2) {\n return _ref5.apply(this, arguments);\n };\n }();\n var handleCreateProject = /*#__PURE__*/function () {\n var _ref6 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee5(name) {\n var newProject;\n return _regeneratorRuntime().wrap(function _callee5$(_context5) {\n while (1) switch (_context5.prev = _context5.next) {\n case 0:\n _context5.prev = 0;\n _context5.next = 3;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_15__.createProject)({\n name: name,\n active: true\n });\n case 3:\n newProject = _context5.sent;\n return _context5.abrupt(\"return\", newProject);\n case 7:\n _context5.prev = 7;\n _context5.t0 = _context5[\"catch\"](0);\n console.error(\"Error creating project:\", _context5.t0);\n throw _context5.t0;\n case 11:\n case \"end\":\n return _context5.stop();\n }\n }, _callee5, null, [[0, 7]]);\n }));\n return function handleCreateProject(_x3) {\n return _ref6.apply(this, arguments);\n };\n }();\n var handleSaveProject = /*#__PURE__*/function () {\n var _ref7 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee6(projectData) {\n var projectsData;\n return _regeneratorRuntime().wrap(function _callee6$(_context6) {\n while (1) switch (_context6.prev = _context6.next) {\n case 0:\n _context6.prev = 0;\n if (!projectData.id) {\n _context6.next = 6;\n break;\n }\n _context6.next = 4;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_15__.updateProject)(projectData.id, projectData);\n case 4:\n _context6.next = 8;\n break;\n case 6:\n _context6.next = 8;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_15__.createProject)(projectData);\n case 8:\n _context6.next = 10;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_15__.fetchProjects)();\n case 10:\n projectsData = _context6.sent;\n setProjects(projectsData);\n closeProjectModal();\n _context6.next = 21;\n break;\n case 15:\n _context6.prev = 15;\n _context6.t0 = _context6[\"catch\"](0);\n console.error(\"Error saving project:\", _context6.t0);\n // Don't close modal if there's an auth error (user will be redirected)\n if (!(0,_utils_authUtils__WEBPACK_IMPORTED_MODULE_17__.isAuthError)(_context6.t0)) {\n _context6.next = 20;\n break;\n }\n return _context6.abrupt(\"return\");\n case 20:\n closeProjectModal();\n case 21:\n case \"end\":\n return _context6.stop();\n }\n }, _callee6, null, [[0, 15]]);\n }));\n return function handleSaveProject(_x4) {\n return _ref7.apply(this, arguments);\n };\n }();\n var handleSaveArea = /*#__PURE__*/function () {\n var _ref8 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee7(areaData) {\n return _regeneratorRuntime().wrap(function _callee7$(_context7) {\n while (1) switch (_context7.prev = _context7.next) {\n case 0:\n _context7.prev = 0;\n if (!areaData.id) {\n _context7.next = 6;\n break;\n }\n _context7.next = 4;\n return (0,_utils_areasService__WEBPACK_IMPORTED_MODULE_13__.updateArea)(areaData.id, areaData);\n case 4:\n _context7.next = 8;\n break;\n case 6:\n _context7.next = 8;\n return (0,_utils_areasService__WEBPACK_IMPORTED_MODULE_13__.createArea)(areaData);\n case 8:\n loadAreas();\n closeAreaModal();\n _context7.next = 18;\n break;\n case 12:\n _context7.prev = 12;\n _context7.t0 = _context7[\"catch\"](0);\n console.error(\"Error saving area:\", _context7.t0);\n // Don't close modal if there's an auth error (user will be redirected)\n if (!(0,_utils_authUtils__WEBPACK_IMPORTED_MODULE_17__.isAuthError)(_context7.t0)) {\n _context7.next = 17;\n break;\n }\n return _context7.abrupt(\"return\");\n case 17:\n closeAreaModal();\n case 18:\n case \"end\":\n return _context7.stop();\n }\n }, _callee7, null, [[0, 12]]);\n }));\n return function handleSaveArea(_x5) {\n return _ref8.apply(this, arguments);\n };\n }();\n var handleSaveTag = /*#__PURE__*/function () {\n var _ref9 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee8(tagData) {\n var tagsData;\n return _regeneratorRuntime().wrap(function _callee8$(_context8) {\n while (1) switch (_context8.prev = _context8.next) {\n case 0:\n _context8.prev = 0;\n if (!tagData.id) {\n _context8.next = 6;\n break;\n }\n _context8.next = 4;\n return (0,_utils_tagsService__WEBPACK_IMPORTED_MODULE_14__.updateTag)(tagData.id, tagData);\n case 4:\n _context8.next = 8;\n break;\n case 6:\n _context8.next = 8;\n return (0,_utils_tagsService__WEBPACK_IMPORTED_MODULE_14__.createTag)(tagData);\n case 8:\n _context8.next = 10;\n return (0,_utils_tagsService__WEBPACK_IMPORTED_MODULE_14__.fetchTags)();\n case 10:\n tagsData = _context8.sent;\n setTags(tagsData);\n closeTagModal();\n _context8.next = 21;\n break;\n case 15:\n _context8.prev = 15;\n _context8.t0 = _context8[\"catch\"](0);\n console.error(\"Error saving tag:\", _context8.t0);\n // Don't close modal if there's an auth error (user will be redirected)\n if (!(0,_utils_authUtils__WEBPACK_IMPORTED_MODULE_17__.isAuthError)(_context8.t0)) {\n _context8.next = 20;\n break;\n }\n return _context8.abrupt(\"return\");\n case 20:\n closeTagModal();\n case 21:\n case \"end\":\n return _context8.stop();\n }\n }, _callee8, null, [[0, 15]]);\n }));\n return function handleSaveTag(_x6) {\n return _ref9.apply(this, arguments);\n };\n }();\n var handleLogout = /*#__PURE__*/function () {\n var _ref10 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee9() {\n var response;\n return _regeneratorRuntime().wrap(function _callee9$(_context9) {\n while (1) switch (_context9.prev = _context9.next) {\n case 0:\n _context9.prev = 0;\n _context9.next = 3;\n return fetch('/api/logout', {\n method: 'GET',\n credentials: 'include'\n });\n case 3:\n response = _context9.sent;\n if (!response.ok) {\n _context9.next = 8;\n break;\n }\n setCurrentUser(null);\n _context9.next = 13;\n break;\n case 8:\n _context9.t0 = console;\n _context9.next = 11;\n return response.json();\n case 11:\n _context9.t1 = _context9.sent;\n _context9.t0.error.call(_context9.t0, 'Logout failed:', _context9.t1);\n case 13:\n _context9.next = 18;\n break;\n case 15:\n _context9.prev = 15;\n _context9.t2 = _context9[\"catch\"](0);\n console.error('Error during logout:', _context9.t2);\n case 18:\n case \"end\":\n return _context9.stop();\n }\n }, _callee9, null, [[0, 15]]);\n }));\n return function handleLogout() {\n return _ref10.apply(this, arguments);\n };\n }();\n var mainContentMarginLeft = isSidebarOpen ? \"ml-72\" : \"ml-0\";\n var isLoading = isNotesLoading || isAreasLoading || isTasksLoading || isProjectsLoading || isTagsLoading;\n var isError = isNotesError || isAreasError || isTasksError || isProjectsError || isTagsError;\n if (isLoading) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"min-h-screen \".concat(isDarkMode ? \"dark\" : \"\")\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Navbar__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n isDarkMode: isDarkMode,\n toggleDarkMode: toggleDarkMode,\n currentUser: currentUser,\n setCurrentUser: setCurrentUser,\n isSidebarOpen: isSidebarOpen,\n setIsSidebarOpen: setIsSidebarOpen\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Sidebar__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n isSidebarOpen: isSidebarOpen,\n setIsSidebarOpen: setIsSidebarOpen,\n currentUser: currentUser,\n isDarkMode: isDarkMode,\n toggleDarkMode: toggleDarkMode,\n openTaskModal: openTaskModal,\n openProjectModal: openProjectModal,\n openNoteModal: openNoteModal,\n openAreaModal: openAreaModal,\n openTagModal: openTagModal,\n notes: notes,\n areas: areas,\n tags: tags\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex-1 flex items-center justify-center bg-gray-100 dark:bg-gray-800 transition-all duration-300 ease-in-out \".concat(mainContentMarginLeft)\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-xl text-gray-700 dark:text-gray-200\"\n }, t('common.loading'))));\n }\n if (isError) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"min-h-screen \".concat(isDarkMode ? \"dark\" : \"\")\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Navbar__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n isDarkMode: isDarkMode,\n toggleDarkMode: toggleDarkMode,\n currentUser: currentUser,\n setCurrentUser: setCurrentUser,\n isSidebarOpen: isSidebarOpen,\n setIsSidebarOpen: setIsSidebarOpen\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Sidebar__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n isSidebarOpen: isSidebarOpen,\n setIsSidebarOpen: setIsSidebarOpen,\n currentUser: currentUser,\n isDarkMode: isDarkMode,\n toggleDarkMode: toggleDarkMode,\n openTaskModal: openTaskModal,\n openProjectModal: openProjectModal,\n openNoteModal: openNoteModal,\n openAreaModal: openAreaModal,\n openTagModal: openTagModal,\n notes: notes,\n areas: areas,\n tags: tags\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex-1 flex flex-col items-center justify-center bg-gray-100 dark:bg-gray-800 transition-all duration-300 ease-in-out \".concat(mainContentMarginLeft)\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-xl text-red-500\"\n }, t('errors.somethingWentWrong'))));\n }\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"min-h-screen \".concat(isDarkMode ? \"dark\" : \"\")\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Navbar__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n isDarkMode: isDarkMode,\n toggleDarkMode: toggleDarkMode,\n currentUser: currentUser,\n setCurrentUser: setCurrentUser,\n isSidebarOpen: isSidebarOpen,\n setIsSidebarOpen: setIsSidebarOpen\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Sidebar__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n isSidebarOpen: isSidebarOpen,\n setIsSidebarOpen: setIsSidebarOpen,\n currentUser: currentUser,\n isDarkMode: isDarkMode,\n toggleDarkMode: toggleDarkMode,\n openTaskModal: openTaskModal,\n openProjectModal: openProjectModal,\n openNoteModal: openNoteModal,\n openAreaModal: openAreaModal,\n openTagModal: openTagModal,\n notes: notes,\n areas: areas,\n tags: tags\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"transition-all duration-300 ease-in-out \".concat(mainContentMarginLeft)\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex flex-col bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-gray-100 min-h-screen overflow-y-auto\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex-grow py-6 px-2 md:px-6 pt-24\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-full max-w-5xl mx-auto\"\n }, children)))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n return openTaskModal('simplified');\n },\n className: \"fixed bottom-6 right-6 bg-blue-500 hover:bg-blue-600 text-white rounded-full p-4 shadow-lg focus:outline-none transform transition-transform duration-200 hover:scale-110 z-50\",\n \"aria-label\": \"Quick Capture\",\n title: t('inbox.captureThought')\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"svg\", {\n className: \"h-6 w-6\",\n fill: \"none\",\n viewBox: \"0 0 24 24\",\n stroke: \"currentColor\",\n strokeWidth: 2\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"path\", {\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n d: \"M12 4v16m8-8H4\"\n }))), isTaskModalOpen && (taskModalType === 'simplified' ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Task_SimplifiedTaskModal__WEBPACK_IMPORTED_MODULE_9__[\"default\"], {\n isOpen: isTaskModalOpen,\n onClose: closeTaskModal,\n onSave: handleSaveTask\n }) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Task_TaskModal__WEBPACK_IMPORTED_MODULE_10__[\"default\"], {\n isOpen: isTaskModalOpen,\n onClose: closeTaskModal,\n task: {\n name: \"\",\n status: \"not_started\"\n },\n onSave: handleSaveTask,\n onDelete: function onDelete() {},\n projects: projects,\n onCreateProject: handleCreateProject\n })), isProjectModalOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Project_ProjectModal__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n isOpen: isProjectModalOpen,\n onClose: closeProjectModal,\n onSave: handleSaveProject,\n areas: areas\n }), isNoteModalOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Note_NoteModal__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n isOpen: isNoteModalOpen,\n onClose: closeNoteModal,\n onSave: handleSaveNote,\n note: selectedNote\n }), isAreaModalOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Area_AreaModal__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n isOpen: isAreaModalOpen,\n onClose: closeAreaModal,\n onSave: handleSaveArea,\n area: selectedArea\n }), isTagModalOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Tag_TagModal__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n isOpen: isTagModalOpen,\n onClose: closeTagModal,\n onSave: handleSaveTag,\n tag: selectedTag\n }));\n};\n_s(Layout, \"eBVkfjBfswhZo5eOvbmGB8HMGqw=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation, _store_useStore__WEBPACK_IMPORTED_MODULE_11__.useStore];\n});\n_c = Layout;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Layout);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"Layout\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/Layout.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Area/AreaDetails.tsx": -/*!**************************************************!*\ - !*** ./frontend/components/Area/AreaDetails.tsx ***! - \**************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router/dist/index.js\");\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router-dom/dist/index.js\");\n/* harmony import */ var _store_useStore__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../store/useStore */ \"./frontend/store/useStore.ts\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\nvar AreaDetails = function AreaDetails() {\n _s();\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_2__.useTranslation)(),\n t = _useTranslation.t;\n var _useParams = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_3__.useParams)(),\n id = _useParams.id;\n var _useStore = (0,_store_useStore__WEBPACK_IMPORTED_MODULE_1__.useStore)(function (state) {\n return state.areasStore;\n }),\n areas = _useStore.areas;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState2 = _slicedToArray(_useState, 2),\n area = _useState2[0],\n setArea = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(true),\n _useState4 = _slicedToArray(_useState3, 2),\n isLoading = _useState4[0],\n setIsLoading = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState6 = _slicedToArray(_useState5, 2),\n isError = _useState6[0],\n setIsError = _useState6[1];\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n if (!areas.length) setIsLoading(true);\n var foundArea = areas.find(function (a) {\n return a.id === Number(id);\n });\n setArea(foundArea || null);\n if (!foundArea) {\n setIsError(true);\n }\n setIsLoading(false);\n }, [id, areas]);\n if (isLoading) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-center h-screen bg-gray-100 dark:bg-gray-900\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-xl font-semibold text-gray-700 dark:text-gray-200\"\n }, t('areas.loading')));\n }\n if (isError || !area) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-center h-screen bg-gray-100 dark:bg-gray-900\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-red-500 text-lg\"\n }, isError ? t('areas.error') : t('areas.notFound')));\n }\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"min-h-screen bg-gray-100 dark:bg-gray-900 p-4 sm:p-6 lg:p-8\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"max-w-5xl mx-auto bg-white dark:bg-gray-800 shadow-lg rounded-lg p-6\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h2\", {\n className: \"text-2xl font-bold text-gray-900 dark:text-white mb-4\"\n }, t('areas.details'), \": \", area === null || area === void 0 ? void 0 : area.name), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-md text-gray-700 dark:text-gray-300\"\n }, area === null || area === void 0 ? void 0 : area.description), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_4__.Link, {\n to: \"/projects?area_id=\".concat(area === null || area === void 0 ? void 0 : area.id),\n className: \"text-blue-600 dark:text-blue-400 hover:underline mt-4 block\"\n }, t('areas.viewProjects', {\n name: area === null || area === void 0 ? void 0 : area.name\n }))));\n};\n_s(AreaDetails, \"ns/RK7Y4Z/3E1GG2nVAA5DMefnU=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_2__.useTranslation, react_router_dom__WEBPACK_IMPORTED_MODULE_3__.useParams, _store_useStore__WEBPACK_IMPORTED_MODULE_1__.useStore];\n});\n_c = AreaDetails;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AreaDetails);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"AreaDetails\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Area/AreaDetails.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Area/AreaModal.tsx": -/*!************************************************!*\ - !*** ./frontend/components/Area/AreaModal.tsx ***! - \************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _Shared_ToastContext__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Shared/ToastContext */ \"./frontend/components/Shared/ToastContext.tsx\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\nvar AreaModal = function AreaModal(_ref) {\n _s();\n var isOpen = _ref.isOpen,\n onClose = _ref.onClose,\n area = _ref.area,\n onSave = _ref.onSave;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_2__.useTranslation)(),\n t = _useTranslation.t;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)({\n id: (area === null || area === void 0 ? void 0 : area.id) || 0,\n name: (area === null || area === void 0 ? void 0 : area.name) || '',\n description: (area === null || area === void 0 ? void 0 : area.description) || ''\n }),\n _useState2 = _slicedToArray(_useState, 2),\n formData = _useState2[0],\n setFormData = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState4 = _slicedToArray(_useState3, 2),\n error = _useState4[0],\n setError = _useState4[1];\n var modalRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState6 = _slicedToArray(_useState5, 2),\n isSubmitting = _useState6[0],\n setIsSubmitting = _useState6[1];\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState8 = _slicedToArray(_useState7, 2),\n isClosing = _useState8[0],\n setIsClosing = _useState8[1];\n var _useToast = (0,_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_1__.useToast)(),\n showSuccessToast = _useToast.showSuccessToast,\n showErrorToast = _useToast.showErrorToast;\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n if (isOpen) {\n setFormData({\n id: (area === null || area === void 0 ? void 0 : area.id) || 0,\n name: (area === null || area === void 0 ? void 0 : area.name) || '',\n description: (area === null || area === void 0 ? void 0 : area.description) || ''\n });\n setError(null);\n }\n }, [isOpen, area]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleClickOutside = function handleClickOutside(event) {\n if (modalRef.current && !modalRef.current.contains(event.target)) {\n handleClose();\n }\n };\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n return function () {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [isOpen]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleKeyDown = function handleKeyDown(event) {\n if (event.key === 'Escape') {\n handleClose();\n }\n };\n if (isOpen) {\n document.addEventListener('keydown', handleKeyDown);\n }\n return function () {\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [isOpen]);\n var handleChange = function handleChange(e) {\n var _e$target = e.target,\n name = _e$target.name,\n value = _e$target.value;\n setFormData(function (prev) {\n return _objectSpread(_objectSpread({}, prev), {}, _defineProperty({}, name, value));\n });\n };\n var handleSubmit = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n if (formData.name.trim()) {\n _context.next = 3;\n break;\n }\n setError(t('errors.areaNameRequired'));\n return _context.abrupt(\"return\");\n case 3:\n setIsSubmitting(true);\n setError(null);\n _context.prev = 5;\n _context.next = 8;\n return onSave(formData);\n case 8:\n showSuccessToast(formData.id ? t('success.areaUpdated') : t('success.areaCreated'));\n handleClose();\n _context.next = 16;\n break;\n case 12:\n _context.prev = 12;\n _context.t0 = _context[\"catch\"](5);\n setError(_context.t0.message);\n showErrorToast(t('errors.failedToSaveArea'));\n case 16:\n _context.prev = 16;\n setIsSubmitting(false);\n return _context.finish(16);\n case 19:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[5, 12, 16, 19]]);\n }));\n return function handleSubmit() {\n return _ref2.apply(this, arguments);\n };\n }();\n var handleClose = function handleClose() {\n setIsClosing(true);\n setTimeout(function () {\n onClose();\n setIsClosing(false);\n }, 300);\n };\n if (!isOpen) return null;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"fixed top-16 left-0 right-0 bottom-0 flex items-start sm:items-center justify-center bg-gray-900 bg-opacity-80 z-40 transition-opacity duration-300 \".concat(isClosing ? 'opacity-0' : 'opacity-100')\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n ref: modalRef,\n className: \"bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-800 sm:rounded-lg sm:shadow-2xl w-full sm:max-w-md overflow-hidden transform transition-transform duration-300 \".concat(isClosing ? 'scale-95' : 'scale-100', \" h-screen sm:h-auto flex flex-col\"),\n style: {\n maxHeight: 'calc(100vh - 4rem)'\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"form\", {\n className: \"flex flex-col flex-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"fieldset\", {\n className: \"flex flex-col flex-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"p-4 space-y-3 flex-1 text-sm overflow-y-auto\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"py-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"text\",\n id: \"areaName\",\n name: \"name\",\n value: formData.name,\n onChange: handleChange,\n required: true,\n className: \"block w-full text-xl font-semibold dark:bg-gray-800 text-black dark:text-white border-b-2 border-gray-200 dark:border-gray-900 focus:outline-none shadow-sm py-2\",\n placeholder: t('forms.areaNamePlaceholder')\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"pb-3\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-xs font-medium text-gray-700 dark:text-gray-300 mb-2\"\n }, t('forms.areaDescription')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"textarea\", {\n id: \"areaDescription\",\n name: \"description\",\n value: formData.description,\n onChange: handleChange,\n rows: 4,\n className: \"block w-full rounded-md shadow-sm p-3 text-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 transition duration-150 ease-in-out\",\n placeholder: t('forms.areaDescriptionPlaceholder')\n })), error && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-red-500\"\n }, error)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"p-3 flex-shrink-0 border-t border-gray-200 dark:border-gray-700 flex justify-end space-x-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: handleClose,\n className: \"px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200 rounded-md hover:bg-gray-300 dark:hover:bg-gray-600 focus:outline-none transition duration-150 ease-in-out\"\n }, t('common.cancel')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: handleSubmit,\n disabled: isSubmitting,\n className: \"px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 focus:outline-none transition duration-150 ease-in-out \".concat(isSubmitting ? 'opacity-50 cursor-not-allowed' : '')\n }, isSubmitting ? t('modals.submitting') : formData.id && formData.id !== 0 ? t('modals.updateArea') : t('modals.createArea')))))));\n};\n_s(AreaModal, \"X0/bmm5jR9Z+QZgSgiSTLA/r3WA=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_2__.useTranslation, _Shared_ToastContext__WEBPACK_IMPORTED_MODULE_1__.useToast];\n});\n_c = AreaModal;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AreaModal);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"AreaModal\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Area/AreaModal.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Areas.tsx": -/*!***************************************!*\ - !*** ./frontend/components/Areas.tsx ***! - \***************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router-dom/dist/index.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/Squares2X2Icon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/PencilSquareIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/TrashIcon.js\");\n/* harmony import */ var _Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Shared/ConfirmDialog */ \"./frontend/components/Shared/ConfirmDialog.tsx\");\n/* harmony import */ var _Area_AreaModal__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Area/AreaModal */ \"./frontend/components/Area/AreaModal.tsx\");\n/* harmony import */ var _store_useStore__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../store/useStore */ \"./frontend/store/useStore.ts\");\n/* harmony import */ var _utils_areasService__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils/areasService */ \"./frontend/utils/areasService.ts\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\n\n\n\nvar Areas = function Areas() {\n _s();\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var _useStore = (0,_store_useStore__WEBPACK_IMPORTED_MODULE_4__.useStore)(function (state) {\n return state.areasStore;\n }),\n areas = _useStore.areas,\n setAreas = _useStore.setAreas,\n setLoading = _useStore.setLoading,\n setError = _useStore.setError;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState2 = _slicedToArray(_useState, 2),\n isAreaModalOpen = _useState2[0],\n setIsAreaModalOpen = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState4 = _slicedToArray(_useState3, 2),\n selectedArea = _useState4[0],\n setSelectedArea = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState6 = _slicedToArray(_useState5, 2),\n isConfirmDialogOpen = _useState6[0],\n setIsConfirmDialogOpen = _useState6[1];\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState8 = _slicedToArray(_useState7, 2),\n areaToDelete = _useState8[0],\n setAreaToDelete = _useState8[1];\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var loadAreas = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var areasData;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.prev = 0;\n _context.next = 3;\n return (0,_utils_areasService__WEBPACK_IMPORTED_MODULE_5__.fetchAreas)();\n case 3:\n areasData = _context.sent;\n setAreas(areasData);\n _context.next = 11;\n break;\n case 7:\n _context.prev = 7;\n _context.t0 = _context[\"catch\"](0);\n console.error('Error fetching areas:', _context.t0);\n setError(true);\n case 11:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[0, 7]]);\n }));\n return function loadAreas() {\n return _ref.apply(this, arguments);\n };\n }();\n loadAreas();\n }, []);\n var handleSaveArea = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(areaData) {\n var updatedAreas;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n setLoading(true);\n _context2.prev = 1;\n if (!areaData.id) {\n _context2.next = 7;\n break;\n }\n _context2.next = 5;\n return (0,_utils_areasService__WEBPACK_IMPORTED_MODULE_5__.updateArea)(areaData.id, {\n name: areaData.name,\n description: areaData.description\n });\n case 5:\n _context2.next = 9;\n break;\n case 7:\n _context2.next = 9;\n return (0,_utils_areasService__WEBPACK_IMPORTED_MODULE_5__.createArea)({\n name: areaData.name,\n description: areaData.description\n });\n case 9:\n _context2.next = 11;\n return (0,_utils_areasService__WEBPACK_IMPORTED_MODULE_5__.fetchAreas)();\n case 11:\n updatedAreas = _context2.sent;\n setAreas(updatedAreas);\n _context2.next = 19;\n break;\n case 15:\n _context2.prev = 15;\n _context2.t0 = _context2[\"catch\"](1);\n console.error('Error saving area:', _context2.t0);\n setError(true);\n case 19:\n _context2.prev = 19;\n setLoading(false);\n setIsAreaModalOpen(false);\n setSelectedArea(null);\n return _context2.finish(19);\n case 24:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, null, [[1, 15, 19, 24]]);\n }));\n return function handleSaveArea(_x) {\n return _ref2.apply(this, arguments);\n };\n }();\n var handleEditArea = function handleEditArea(area) {\n setSelectedArea(area);\n setIsAreaModalOpen(true);\n };\n var handleCreateArea = function handleCreateArea() {\n setSelectedArea(null);\n setIsAreaModalOpen(true);\n };\n var openConfirmDialog = function openConfirmDialog(area) {\n setAreaToDelete(area);\n setIsConfirmDialogOpen(true);\n };\n var handleDeleteArea = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {\n var updatedAreas;\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n if (areaToDelete) {\n _context3.next = 2;\n break;\n }\n return _context3.abrupt(\"return\");\n case 2:\n setLoading(true);\n _context3.prev = 3;\n _context3.next = 6;\n return (0,_utils_areasService__WEBPACK_IMPORTED_MODULE_5__.deleteArea)(areaToDelete.id);\n case 6:\n _context3.next = 8;\n return (0,_utils_areasService__WEBPACK_IMPORTED_MODULE_5__.fetchAreas)();\n case 8:\n updatedAreas = _context3.sent;\n setAreas(updatedAreas);\n setIsConfirmDialogOpen(false);\n setAreaToDelete(null);\n _context3.next = 18;\n break;\n case 14:\n _context3.prev = 14;\n _context3.t0 = _context3[\"catch\"](3);\n console.error('Error deleting area:', _context3.t0);\n setError(true);\n case 18:\n _context3.prev = 18;\n setLoading(false);\n return _context3.finish(18);\n case 21:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3, null, [[3, 14, 18, 21]]);\n }));\n return function handleDeleteArea() {\n return _ref3.apply(this, arguments);\n };\n }();\n var closeConfirmDialog = function closeConfirmDialog() {\n setIsConfirmDialogOpen(false);\n setAreaToDelete(null);\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex justify-center px-4 lg:px-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-full max-w-5xl\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-between mb-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n className: \"h-6 w-6 mr-2 text-gray-900 dark:text-white\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h2\", {\n className: \"text-2xl font-light text-gray-900 dark:text-white\"\n }, t('areas.title'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: handleCreateArea,\n className: \"bg-blue-500 text-white rounded-md px-4 py-2 hover:bg-blue-600\"\n }, t('areas.addArea'))), areas.length === 0 ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-gray-700 dark:text-gray-300\"\n }, t('areas.noAreasFound')) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"ul\", {\n className: \"space-y-2\"\n }, areas.map(function (area) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"li\", {\n key: area.id,\n className: \"bg-white dark:bg-gray-900 shadow rounded-lg p-4 flex justify-between items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex-grow overflow-hidden pr-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_7__.Link, {\n to: \"/projects?area_id=\".concat(area.id),\n className: \"text-md font-semibold text-gray-900 dark:text-gray-100 hover:underline block\"\n }, area.name), area.description && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-xs text-gray-600 dark:text-gray-400 mt-1 truncate\"\n }, area.description)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex space-x-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n return handleEditArea(area);\n },\n className: \"text-gray-500 hover:text-blue-700 dark:hover:text-blue-300 focus:outline-none\",\n \"aria-label\": t('areas.editAreaAriaLabel', {\n name: area.name\n }),\n title: t('areas.editAreaTitle', {\n name: area.name\n })\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n className: \"h-5 w-5\"\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n return openConfirmDialog(area);\n },\n className: \"text-gray-500 hover:text-red-700 dark:hover:text-red-300 focus:outline-none\",\n \"aria-label\": t('areas.deleteAreaAriaLabel', {\n name: area.name\n }),\n title: t('areas.deleteAreaTitle', {\n name: area.name\n })\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_9__[\"default\"], {\n className: \"h-5 w-5\"\n }))));\n })), isAreaModalOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Area_AreaModal__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n isOpen: isAreaModalOpen,\n onClose: function onClose() {\n return setIsAreaModalOpen(false);\n },\n onSave: handleSaveArea,\n area: selectedArea\n }), isConfirmDialogOpen && areaToDelete && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n title: t('modals.deleteArea.title'),\n message: t('modals.deleteArea.message', {\n name: areaToDelete.name\n }),\n onConfirm: handleDeleteArea,\n onCancel: closeConfirmDialog\n })));\n};\n_s(Areas, \"y233SdergRQ16O2WxrcQu2qV2lk=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation, _store_useStore__WEBPACK_IMPORTED_MODULE_4__.useStore];\n});\n_c = Areas;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Areas);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"Areas\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Areas.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Inbox/InboxItemDetail.tsx": -/*!*******************************************************!*\ - !*** ./frontend/components/Inbox/InboxItemDetail.tsx ***! - \*******************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! date-fns */ \"./node_modules/date-fns/format.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/PencilIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/EllipsisVerticalIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/TrashIcon.js\");\n/* harmony import */ var _Shared_ToastContext__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Shared/ToastContext */ \"./frontend/components/Shared/ToastContext.tsx\");\n/* harmony import */ var _Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Shared/ConfirmDialog */ \"./frontend/components/Shared/ConfirmDialog.tsx\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\n\nvar InboxItemDetail = function InboxItemDetail(_ref) {\n _s();\n var item = _ref.item,\n onProcess = _ref.onProcess,\n onDelete = _ref.onDelete,\n onUpdate = _ref.onUpdate,\n openTaskModal = _ref.openTaskModal,\n openProjectModal = _ref.openProjectModal,\n openNoteModal = _ref.openNoteModal;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var _useToast = (0,_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_2__.useToast)(),\n showSuccessToast = _useToast.showSuccessToast,\n showErrorToast = _useToast.showErrorToast;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState2 = _slicedToArray(_useState, 2),\n dropdownOpen = _useState2[0],\n setDropdownOpen = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState4 = _slicedToArray(_useState3, 2),\n showConfirmDialog = _useState4[0],\n setShowConfirmDialog = _useState4[1];\n var dropdownRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState6 = _slicedToArray(_useState5, 2),\n loading = _useState6[0],\n setLoading = _useState6[1];\n\n // Handle click outside of dropdown\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleClickOutside = function handleClickOutside(event) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {\n setDropdownOpen(false);\n }\n };\n if (dropdownOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n return function () {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [dropdownOpen]);\n var handleConvertToTask = function handleConvertToTask() {\n var newTask = {\n name: item.content,\n status: 'not_started',\n priority: 'medium'\n };\n\n // First close the dropdown\n setDropdownOpen(false);\n\n // Use a simple timeout to ensure the dropdown closes before opening modal\n setTimeout(function () {\n if (item.id !== undefined) {\n openTaskModal(newTask, item.id);\n } else {\n openTaskModal(newTask);\n }\n }, 50);\n };\n var handleConvertToProject = function handleConvertToProject() {\n var newProject = {\n name: item.content,\n description: '',\n active: true\n };\n\n // First close the dropdown\n setDropdownOpen(false);\n\n // Use a simple timeout to ensure the dropdown closes before opening modal\n setTimeout(function () {\n if (item.id !== undefined) {\n openProjectModal(newProject, item.id);\n } else {\n openProjectModal(newProject);\n }\n }, 50);\n };\n var handleConvertToNote = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var title, content, isBookmark, _yield$import, isUrl, extractUrlTitle, result, tagObjects, newNote;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n title = item.content.split('\\n')[0] || item.content.substring(0, 50);\n content = item.content;\n isBookmark = false;\n _context.prev = 3;\n _context.next = 6;\n return Promise.resolve(/*! import() */).then(__webpack_require__.bind(__webpack_require__, /*! ../../utils/urlService */ \"./frontend/utils/urlService.ts\"));\n case 6:\n _yield$import = _context.sent;\n isUrl = _yield$import.isUrl;\n extractUrlTitle = _yield$import.extractUrlTitle;\n if (!isUrl(item.content.trim())) {\n _context.next = 16;\n break;\n }\n setLoading(true);\n _context.next = 13;\n return extractUrlTitle(item.content.trim());\n case 13:\n result = _context.sent;\n setLoading(false);\n if (result && result.title) {\n title = result.title;\n content = item.content;\n isBookmark = true;\n }\n case 16:\n _context.next = 21;\n break;\n case 18:\n _context.prev = 18;\n _context.t0 = _context[\"catch\"](3);\n console.error(\"Error checking URL or extracting title:\", _context.t0);\n case 21:\n // Simple array of tag objects for the note\n tagObjects = isBookmark ? [{\n name: \"bookmark\"\n }] : [];\n console.log(\"Creating note with bookmark tag:\", isBookmark);\n newNote = {\n title: title,\n content: content,\n tags: tagObjects\n }; // First close the dropdown\n setDropdownOpen(false);\n\n // Use a simple timeout to ensure the dropdown closes before opening modal\n setTimeout(function () {\n if (item.id !== undefined) {\n openNoteModal(newNote, item.id);\n } else {\n openNoteModal(newNote);\n }\n }, 50);\n case 26:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[3, 18]]);\n }));\n return function handleConvertToNote() {\n return _ref2.apply(this, arguments);\n };\n }();\n var formattedDate = item.created_at ? (0,date_fns__WEBPACK_IMPORTED_MODULE_4__.format)(new Date(item.created_at), 'MMM dd, yyyy HH:mm') : '';\n var handleDelete = function handleDelete() {\n setShowConfirmDialog(true);\n };\n var confirmDelete = function confirmDelete() {\n if (item.id !== undefined) {\n onDelete(item.id);\n }\n setShowConfirmDialog(false);\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"rounded-lg shadow-sm bg-white dark:bg-gray-900 mt-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-between px-4 py-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex-1 mr-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-base font-medium text-gray-900 dark:text-gray-300 break-words\"\n }, item.content, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"ml-3 text-xs text-gray-500 dark:text-gray-600\"\n }, formattedDate), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"ml-2 text-xs bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-100 rounded p-1\"\n }, item.source))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center space-x-0\"\n }, loading && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"spinner\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n if (onUpdate && item.id !== undefined) {\n onUpdate(item.id, item.content);\n }\n },\n className: \"p-2 text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-full\",\n title: t('common.edit')\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n className: \"h-5 w-5\"\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"relative\",\n ref: dropdownRef\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n return setDropdownOpen(!dropdownOpen);\n },\n className: \"p-2 text-blue-600 dark:text-blue-400 hover:bg-blue-100 dark:hover:bg-blue-900 rounded-full\",\n title: t('inbox.convertTo', 'Convert to')\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n className: \"h-5 w-5\"\n })), dropdownOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"absolute right-0 mt-2 w-40 bg-white dark:bg-gray-700 shadow-md rounded-md z-10\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"ul\", {\n className: \"py-1\",\n role: \"menu\",\n \"aria-orientation\": \"vertical\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"li\", {\n className: \"px-4 py-1 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600 cursor-pointer\",\n onClick: handleConvertToTask,\n role: \"menuitem\"\n }, t('inbox.createTask')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"li\", {\n className: \"px-4 py-1 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600 cursor-pointer\",\n onClick: handleConvertToProject,\n role: \"menuitem\"\n }, t('inbox.createProject')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"li\", {\n className: \"px-4 py-1 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600 cursor-pointer\",\n onClick: handleConvertToNote,\n role: \"menuitem\"\n }, t('inbox.createNote', 'Create Note'))))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: handleDelete,\n className: \"p-2 text-red-600 dark:text-red-400 hover:bg-red-100 dark:hover:bg-red-900 rounded-full\",\n title: t('common.delete')\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n className: \"h-5 w-5\"\n })))), showConfirmDialog && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n title: t('inbox.deleteConfirmTitle', 'Delete Item'),\n message: t('inbox.deleteConfirmMessage', 'Are you sure you want to delete this inbox item? This action cannot be undone.'),\n onConfirm: confirmDelete,\n onCancel: function onCancel() {\n return setShowConfirmDialog(false);\n }\n }));\n};\n_s(InboxItemDetail, \"kzVgvdTG2wudoD/xw3FHH+Mpn/8=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation, _Shared_ToastContext__WEBPACK_IMPORTED_MODULE_2__.useToast];\n});\n_c = InboxItemDetail;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (InboxItemDetail);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"InboxItemDetail\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Inbox/InboxItemDetail.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Inbox/InboxItems.tsx": -/*!**************************************************!*\ - !*** ./frontend/components/Inbox/InboxItems.tsx ***! - \**************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _utils_inboxService__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../utils/inboxService */ \"./frontend/utils/inboxService.ts\");\n/* harmony import */ var _InboxItemDetail__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./InboxItemDetail */ \"./frontend/components/Inbox/InboxItemDetail.tsx\");\n/* harmony import */ var _Shared_ToastContext__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Shared/ToastContext */ \"./frontend/components/Shared/ToastContext.tsx\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/InboxIcon.js\");\n/* harmony import */ var _Shared_LoadingScreen__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../Shared/LoadingScreen */ \"./frontend/components/Shared/LoadingScreen.tsx\");\n/* harmony import */ var _Task_TaskModal__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../Task/TaskModal */ \"./frontend/components/Task/TaskModal.tsx\");\n/* harmony import */ var _Project_ProjectModal__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../Project/ProjectModal */ \"./frontend/components/Project/ProjectModal.tsx\");\n/* harmony import */ var _Note_NoteModal__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../Note/NoteModal */ \"./frontend/components/Note/NoteModal.tsx\");\n/* harmony import */ var _Task_SimplifiedTaskModal__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../Task/SimplifiedTaskModal */ \"./frontend/components/Task/SimplifiedTaskModal.tsx\");\n/* harmony import */ var _utils_projectsService__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../utils/projectsService */ \"./frontend/utils/projectsService.ts\");\n/* harmony import */ var _utils_tasksService__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../../utils/tasksService */ \"./frontend/utils/tasksService.ts\");\n/* harmony import */ var _utils_notesService__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../../utils/notesService */ \"./frontend/utils/notesService.ts\");\n/* harmony import */ var _utils_urlService__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../../utils/urlService */ \"./frontend/utils/urlService.ts\");\n/* harmony import */ var _store_useStore__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../../store/useStore */ \"./frontend/store/useStore.ts\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar InboxItems = function InboxItems() {\n _s();\n var _inboxItems$find;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_4__.useTranslation)(),\n t = _useTranslation.t;\n var _useToast = (0,_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_3__.useToast)(),\n showSuccessToast = _useToast.showSuccessToast,\n showErrorToast = _useToast.showErrorToast;\n\n // Access store data\n var _useStore = (0,_store_useStore__WEBPACK_IMPORTED_MODULE_14__.useStore)(function (state) {\n return state.inboxStore;\n }),\n inboxItems = _useStore.inboxItems,\n isLoading = _useStore.isLoading;\n\n // Modal states\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState2 = _slicedToArray(_useState, 2),\n isTaskModalOpen = _useState2[0],\n setIsTaskModalOpen = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState4 = _slicedToArray(_useState3, 2),\n isProjectModalOpen = _useState4[0],\n setIsProjectModalOpen = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState6 = _slicedToArray(_useState5, 2),\n isNoteModalOpen = _useState6[0],\n setIsNoteModalOpen = _useState6[1];\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState8 = _slicedToArray(_useState7, 2),\n isEditModalOpen = _useState8[0],\n setIsEditModalOpen = _useState8[1];\n\n // Data for modals\n var _useState9 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState10 = _slicedToArray(_useState9, 2),\n taskToEdit = _useState10[0],\n setTaskToEdit = _useState10[1];\n var _useState11 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState12 = _slicedToArray(_useState11, 2),\n projectToEdit = _useState12[0],\n setProjectToEdit = _useState12[1];\n var _useState13 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState14 = _slicedToArray(_useState13, 2),\n noteToEdit = _useState14[0],\n setNoteToEdit = _useState14[1];\n\n // Track the current inbox item ID being converted (for task/project/note conversion)\n var _useState15 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState16 = _slicedToArray(_useState15, 2),\n currentConversionItemId = _useState16[0],\n setCurrentConversionItemId = _useState16[1];\n\n // Track the current inbox item being edited\n var _useState17 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState18 = _slicedToArray(_useState17, 2),\n itemToEdit = _useState18[0],\n setItemToEdit = _useState18[1];\n\n // Fetch projects for modals\n var _useState19 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)([]),\n _useState20 = _slicedToArray(_useState19, 2),\n projects = _useState20[0],\n setProjects = _useState20[1];\n\n // Wrapped in useCallback to prevent dependency issues in useEffect\n var refreshInboxItems = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(function () {\n (0,_utils_inboxService__WEBPACK_IMPORTED_MODULE_1__.loadInboxItemsToStore)();\n }, []);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n // Initial data loading\n refreshInboxItems();\n loadProjects();\n\n // Set up an event listener for force reload\n var handleForceReload = function handleForceReload() {\n // Wait a short time to ensure the backend has processed the new item\n setTimeout(function () {\n refreshInboxItems();\n }, 500);\n };\n\n // Handler for the inboxItemsUpdated custom event\n var handleInboxItemsUpdated = function handleInboxItemsUpdated(event) {\n console.log(\"Received inboxItemsUpdated event: \".concat(event.detail.count, \" new items\"));\n\n // Show toast notifications for new items\n if (event.detail.count > 0) {\n // Show notification for the first new item\n showSuccessToast(t('inbox.newTelegramItem', 'New item from Telegram: {{content}}', {\n content: event.detail.firstItemContent\n }));\n\n // If multiple new items, show a summary notification as well\n if (event.detail.count > 1) {\n showSuccessToast(t('inbox.multipleNewItems', '{{count}} more new items added', {\n count: event.detail.count - 1\n }));\n }\n }\n };\n\n // Set up polling for new inbox items (especially from Telegram)\n // This ensures real-time updates when items are added externally\n var pollInterval = setInterval(function () {\n refreshInboxItems();\n }, 5000); // Check for new items every 5 seconds\n\n // Add event listeners\n window.addEventListener('forceInboxReload', handleForceReload);\n window.addEventListener('inboxItemsUpdated', handleInboxItemsUpdated);\n return function () {\n clearInterval(pollInterval);\n window.removeEventListener('forceInboxReload', handleForceReload);\n window.removeEventListener('inboxItemsUpdated', handleInboxItemsUpdated);\n };\n }, [refreshInboxItems, showSuccessToast, t]);\n\n // Load projects for the modals\n var loadProjects = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var projectData;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.prev = 0;\n _context.next = 3;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_10__.fetchProjects)();\n case 3:\n projectData = _context.sent;\n setProjects(projectData);\n _context.next = 10;\n break;\n case 7:\n _context.prev = 7;\n _context.t0 = _context[\"catch\"](0);\n console.error('Failed to load projects:', _context.t0);\n case 10:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[0, 7]]);\n }));\n return function loadProjects() {\n return _ref.apply(this, arguments);\n };\n }();\n var handleProcessItem = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(id) {\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n _context2.prev = 0;\n _context2.next = 3;\n return (0,_utils_inboxService__WEBPACK_IMPORTED_MODULE_1__.processInboxItemWithStore)(id);\n case 3:\n showSuccessToast(t('inbox.itemProcessed'));\n _context2.next = 10;\n break;\n case 6:\n _context2.prev = 6;\n _context2.t0 = _context2[\"catch\"](0);\n console.error('Failed to process inbox item:', _context2.t0);\n showErrorToast(t('inbox.processError'));\n case 10:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, null, [[0, 6]]);\n }));\n return function handleProcessItem(_x) {\n return _ref2.apply(this, arguments);\n };\n }();\n var handleUpdateItem = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(id) {\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n // When edit button is clicked, we open the SimplifiedTaskModal instead of doing inline editing\n setItemToEdit(id);\n setIsEditModalOpen(true);\n case 2:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3);\n }));\n return function handleUpdateItem(_x2) {\n return _ref3.apply(this, arguments);\n };\n }();\n var handleSaveEditedItem = /*#__PURE__*/function () {\n var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4(text) {\n return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n while (1) switch (_context4.prev = _context4.next) {\n case 0:\n _context4.prev = 0;\n if (!(itemToEdit !== null)) {\n _context4.next = 5;\n break;\n }\n _context4.next = 4;\n return (0,_utils_inboxService__WEBPACK_IMPORTED_MODULE_1__.updateInboxItemWithStore)(itemToEdit, text);\n case 4:\n showSuccessToast(t('inbox.itemUpdated'));\n case 5:\n setIsEditModalOpen(false);\n setItemToEdit(null);\n _context4.next = 13;\n break;\n case 9:\n _context4.prev = 9;\n _context4.t0 = _context4[\"catch\"](0);\n console.error('Failed to update inbox item:', _context4.t0);\n showErrorToast(t('inbox.updateError'));\n case 13:\n case \"end\":\n return _context4.stop();\n }\n }, _callee4, null, [[0, 9]]);\n }));\n return function handleSaveEditedItem(_x3) {\n return _ref4.apply(this, arguments);\n };\n }();\n var handleDeleteItem = /*#__PURE__*/function () {\n var _ref5 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee5(id) {\n return _regeneratorRuntime().wrap(function _callee5$(_context5) {\n while (1) switch (_context5.prev = _context5.next) {\n case 0:\n _context5.prev = 0;\n _context5.next = 3;\n return (0,_utils_inboxService__WEBPACK_IMPORTED_MODULE_1__.deleteInboxItemWithStore)(id);\n case 3:\n showSuccessToast(t('inbox.itemDeleted'));\n _context5.next = 10;\n break;\n case 6:\n _context5.prev = 6;\n _context5.t0 = _context5[\"catch\"](0);\n console.error('Failed to delete inbox item:', _context5.t0);\n showErrorToast(t('inbox.deleteError'));\n case 10:\n case \"end\":\n return _context5.stop();\n }\n }, _callee5, null, [[0, 6]]);\n }));\n return function handleDeleteItem(_x4) {\n return _ref5.apply(this, arguments);\n };\n }();\n\n // Modal handlers\n var handleOpenTaskModal = function handleOpenTaskModal(task, inboxItemId) {\n setTaskToEdit(task);\n if (inboxItemId) {\n setCurrentConversionItemId(inboxItemId);\n }\n setIsTaskModalOpen(true);\n };\n var handleOpenProjectModal = function handleOpenProjectModal(project, inboxItemId) {\n setProjectToEdit(project);\n if (inboxItemId) {\n setCurrentConversionItemId(inboxItemId);\n }\n setIsProjectModalOpen(true);\n };\n var handleOpenNoteModal = function handleOpenNoteModal(note, inboxItemId) {\n // If note has content that's a URL, ensure it has a bookmark tag\n if (note && note.content && (0,_utils_urlService__WEBPACK_IMPORTED_MODULE_13__.isUrl)(note.content.trim())) {\n if (!note.tags) {\n note.tags = [{\n name: 'bookmark'\n }];\n } else if (!note.tags.some(function (tag) {\n return tag.name === 'bookmark';\n })) {\n note.tags.push({\n name: 'bookmark'\n });\n }\n console.log(\"Opening NoteModal with URL content and tags:\", note.tags);\n }\n setNoteToEdit(note);\n if (inboxItemId) {\n setCurrentConversionItemId(inboxItemId);\n }\n setIsNoteModalOpen(true);\n };\n var handleSaveTask = /*#__PURE__*/function () {\n var _ref6 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee6(task) {\n return _regeneratorRuntime().wrap(function _callee6$(_context6) {\n while (1) switch (_context6.prev = _context6.next) {\n case 0:\n _context6.prev = 0;\n _context6.next = 3;\n return (0,_utils_tasksService__WEBPACK_IMPORTED_MODULE_11__.createTask)(task);\n case 3:\n showSuccessToast(t('task.createSuccess'));\n\n // Process the inbox item after successful task creation\n if (!(currentConversionItemId !== null)) {\n _context6.next = 8;\n break;\n }\n _context6.next = 7;\n return handleProcessItem(currentConversionItemId);\n case 7:\n setCurrentConversionItemId(null);\n case 8:\n setIsTaskModalOpen(false);\n _context6.next = 15;\n break;\n case 11:\n _context6.prev = 11;\n _context6.t0 = _context6[\"catch\"](0);\n console.error('Failed to create task:', _context6.t0);\n showErrorToast(t('task.createError'));\n case 15:\n case \"end\":\n return _context6.stop();\n }\n }, _callee6, null, [[0, 11]]);\n }));\n return function handleSaveTask(_x5) {\n return _ref6.apply(this, arguments);\n };\n }();\n var handleSaveProject = /*#__PURE__*/function () {\n var _ref7 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee7(project) {\n return _regeneratorRuntime().wrap(function _callee7$(_context7) {\n while (1) switch (_context7.prev = _context7.next) {\n case 0:\n _context7.prev = 0;\n _context7.next = 3;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_10__.createProject)(project);\n case 3:\n showSuccessToast(t('project.createSuccess'));\n\n // Process the inbox item after successful project creation\n if (!(currentConversionItemId !== null)) {\n _context7.next = 8;\n break;\n }\n _context7.next = 7;\n return handleProcessItem(currentConversionItemId);\n case 7:\n setCurrentConversionItemId(null);\n case 8:\n setIsProjectModalOpen(false);\n _context7.next = 15;\n break;\n case 11:\n _context7.prev = 11;\n _context7.t0 = _context7[\"catch\"](0);\n console.error('Failed to create project:', _context7.t0);\n showErrorToast(t('project.createError'));\n case 15:\n case \"end\":\n return _context7.stop();\n }\n }, _callee7, null, [[0, 11]]);\n }));\n return function handleSaveProject(_x6) {\n return _ref7.apply(this, arguments);\n };\n }();\n var handleSaveNote = /*#__PURE__*/function () {\n var _ref8 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee8(note) {\n var noteContent, isBookmarkContent;\n return _regeneratorRuntime().wrap(function _callee8$(_context8) {\n while (1) switch (_context8.prev = _context8.next) {\n case 0:\n _context8.prev = 0;\n // Check if the content appears to be a URL and add the bookmark tag\n noteContent = note.content || '';\n isBookmarkContent = (0,_utils_urlService__WEBPACK_IMPORTED_MODULE_13__.isUrl)(noteContent.trim()); // Ensure tags property exists\n if (!note.tags) {\n note.tags = [];\n }\n\n // Add a bookmark tag if content is a URL and doesn't already have the tag\n if (isBookmarkContent && !note.tags.some(function (tag) {\n return tag.name === 'bookmark';\n })) {\n // Use spread operator to create a new array with the bookmark tag added\n note.tags = [].concat(_toConsumableArray(note.tags), [{\n name: 'bookmark'\n }]);\n }\n console.log('Creating note with tags:', JSON.stringify(note.tags));\n\n // Create the note with proper tags\n _context8.next = 8;\n return (0,_utils_notesService__WEBPACK_IMPORTED_MODULE_12__.createNote)(note);\n case 8:\n showSuccessToast(t('note.createSuccess', 'Note created successfully'));\n\n // Process the inbox item after successful note creation\n if (!(currentConversionItemId !== null)) {\n _context8.next = 13;\n break;\n }\n _context8.next = 12;\n return handleProcessItem(currentConversionItemId);\n case 12:\n setCurrentConversionItemId(null);\n case 13:\n setIsNoteModalOpen(false);\n _context8.next = 20;\n break;\n case 16:\n _context8.prev = 16;\n _context8.t0 = _context8[\"catch\"](0);\n console.error('Failed to create note:', _context8.t0);\n showErrorToast(t('note.createError', 'Failed to create note'));\n case 20:\n case \"end\":\n return _context8.stop();\n }\n }, _callee8, null, [[0, 16]]);\n }));\n return function handleSaveNote(_x7) {\n return _ref8.apply(this, arguments);\n };\n }();\n var handleCreateProject = /*#__PURE__*/function () {\n var _ref9 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee9(name) {\n var project;\n return _regeneratorRuntime().wrap(function _callee9$(_context9) {\n while (1) switch (_context9.prev = _context9.next) {\n case 0:\n _context9.prev = 0;\n _context9.next = 3;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_10__.createProject)({\n name: name,\n active: true\n });\n case 3:\n project = _context9.sent;\n showSuccessToast(t('project.createSuccess'));\n return _context9.abrupt(\"return\", project);\n case 8:\n _context9.prev = 8;\n _context9.t0 = _context9[\"catch\"](0);\n console.error('Failed to create project:', _context9.t0);\n showErrorToast(t('project.createError'));\n throw _context9.t0;\n case 13:\n case \"end\":\n return _context9.stop();\n }\n }, _callee9, null, [[0, 8]]);\n }));\n return function handleCreateProject(_x8) {\n return _ref9.apply(this, arguments);\n };\n }();\n if (isLoading) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Shared_LoadingScreen__WEBPACK_IMPORTED_MODULE_5__[\"default\"], null);\n }\n if (inboxItems.length === 0) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex flex-col items-center justify-center p-8 space-y-4 text-center text-gray-600 dark:text-gray-300\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_15__[\"default\"], {\n className: \"h-16 w-16\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h3\", {\n className: \"text-xl font-semibold\"\n }, t('inbox.empty')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", null, t('inbox.emptyDescription')));\n }\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"container mx-auto p-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center mb-8\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_15__[\"default\"], {\n className: \"h-6 w-6 mr-2\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h1\", {\n className: \"text-2xl font-light\"\n }, t('inbox.title'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"mb-6 text-sm text-gray-500 dark:text-gray-400\"\n }, t('taskViews.inbox', 'Inbox is where all uncategorized tasks are located. Tasks that have not been assigned to a project or don\\'t have a due date will appear here. This is your \\'brain dump\\' area where you can quickly note down tasks and organize them later.')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"space-y-2\"\n }, inboxItems.map(function (item) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_InboxItemDetail__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n key: item.id,\n item: item,\n onProcess: handleProcessItem,\n onDelete: handleDeleteItem,\n onUpdate: handleUpdateItem,\n openTaskModal: handleOpenTaskModal,\n openProjectModal: handleOpenProjectModal,\n openNoteModal: handleOpenNoteModal\n });\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Task_TaskModal__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n isOpen: isTaskModalOpen,\n onClose: function onClose() {\n setIsTaskModalOpen(false);\n setTaskToEdit(null);\n },\n task: taskToEdit || {\n name: '',\n status: 'not_started',\n priority: 'medium'\n },\n onSave: handleSaveTask,\n onDelete: function onDelete() {} // No need to delete since it's a new task\n ,\n projects: projects,\n onCreateProject: handleCreateProject\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Project_ProjectModal__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n isOpen: isProjectModalOpen,\n onClose: function onClose() {\n setIsProjectModalOpen(false);\n setProjectToEdit(null);\n },\n onSave: handleSaveProject,\n project: projectToEdit || undefined,\n areas: []\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Note_NoteModal__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n isOpen: isNoteModalOpen,\n onClose: function onClose() {\n setIsNoteModalOpen(false);\n setNoteToEdit(null);\n },\n onSave: handleSaveNote,\n note: noteToEdit || {\n title: '',\n content: ''\n }\n }), isEditModalOpen && itemToEdit !== null && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Task_SimplifiedTaskModal__WEBPACK_IMPORTED_MODULE_9__[\"default\"], {\n isOpen: isEditModalOpen,\n onClose: function onClose() {\n setIsEditModalOpen(false);\n setItemToEdit(null);\n },\n onSave: /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee10() {\n return _regeneratorRuntime().wrap(function _callee10$(_context10) {\n while (1) switch (_context10.prev = _context10.next) {\n case 0:\n case \"end\":\n return _context10.stop();\n }\n }, _callee10);\n })) // Not used in edit mode\n ,\n initialText: ((_inboxItems$find = inboxItems.find(function (item) {\n return item.id === itemToEdit;\n })) === null || _inboxItems$find === void 0 ? void 0 : _inboxItems$find.content) || \"\",\n editMode: true,\n onEdit: handleSaveEditedItem\n }));\n};\n_s(InboxItems, \"nq0ODX7Tcz9ugYgcI0G8lAoMtHA=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_4__.useTranslation, _Shared_ToastContext__WEBPACK_IMPORTED_MODULE_3__.useToast, _store_useStore__WEBPACK_IMPORTED_MODULE_14__.useStore];\n});\n_c = InboxItems;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (InboxItems);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"InboxItems\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Inbox/InboxItems.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Login.tsx": -/*!***************************************!*\ - !*** ./frontend/components/Login.tsx ***! - \***************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router/dist/index.js\");\n/* harmony import */ var i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! i18next */ \"./node_modules/i18next/dist/esm/i18next.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\nvar Login = function Login() {\n _s();\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(''),\n _useState2 = _slicedToArray(_useState, 2),\n email = _useState2[0],\n setEmail = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(''),\n _useState4 = _slicedToArray(_useState3, 2),\n password = _useState4[0],\n setPassword = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState6 = _slicedToArray(_useState5, 2),\n error = _useState6[0],\n setError = _useState6[1];\n var navigate = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_3__.useNavigate)();\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_2__.useTranslation)(),\n t = _useTranslation.t;\n var handleSubmit = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(e) {\n var response, data;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n e.preventDefault();\n _context.prev = 1;\n _context.next = 4;\n return fetch('/api/login', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n email: email,\n password: password\n }),\n credentials: 'include'\n });\n case 4:\n response = _context.sent;\n _context.next = 7;\n return response.json();\n case 7:\n data = _context.sent;\n if (!response.ok) {\n _context.next = 19;\n break;\n }\n console.log('Login successful:', data);\n if (!(data.user && data.user.language)) {\n _context.next = 15;\n break;\n }\n console.log('Setting language from login response:', data.user.language);\n _context.next = 14;\n return i18next__WEBPACK_IMPORTED_MODULE_1__[\"default\"].changeLanguage(data.user.language);\n case 14:\n console.log('Language changed to:', i18next__WEBPACK_IMPORTED_MODULE_1__[\"default\"].language);\n case 15:\n // Trigger a custom event to notify App component\n window.dispatchEvent(new CustomEvent('userLoggedIn', {\n detail: data.user\n }));\n navigate('/today');\n _context.next = 20;\n break;\n case 19:\n setError(data.errors[0] || 'Login failed. Please try again.');\n case 20:\n _context.next = 26;\n break;\n case 22:\n _context.prev = 22;\n _context.t0 = _context[\"catch\"](1);\n setError('An error occurred. Please try again.');\n console.error('Error during login:', _context.t0);\n case 26:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[1, 22]]);\n }));\n return function handleSubmit(_x) {\n return _ref.apply(this, arguments);\n };\n }();\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"bg-gray-100 flex flex-col items-center justify-center min-h-screen px-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h1\", {\n className: \"text-5xl font-bold text-gray-300 mb-6\"\n }, \"tududi\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"bg-white p-8 rounded-lg shadow-md w-full max-w-sm\"\n }, error && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4 text-center text-red-500\"\n }, error), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"form\", {\n onSubmit: handleSubmit\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n htmlFor: \"email\",\n className: \"block text-gray-600 mb-1\"\n }, t('auth.email', 'Email')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"email\",\n id: \"email\",\n name: \"email\",\n value: email,\n onChange: function onChange(e) {\n return setEmail(e.target.value);\n },\n className: \"w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500\",\n required: true\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n htmlFor: \"password\",\n className: \"block text-gray-600 mb-1\"\n }, t('auth.password', 'Password')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"password\",\n id: \"password\",\n name: \"password\",\n value: password,\n onChange: function onChange(e) {\n return setPassword(e.target.value);\n },\n className: \"w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500\",\n required: true\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"submit\",\n className: \"w-full bg-blue-500 text-white py-2 rounded-lg hover:bg-blue-600 transition-colors\"\n }, t('auth.login', 'Login')))));\n};\n_s(Login, \"p+CSpJk3UEXSCL3mEICWIDrV9HY=\", false, function () {\n return [react_router_dom__WEBPACK_IMPORTED_MODULE_3__.useNavigate, react_i18next__WEBPACK_IMPORTED_MODULE_2__.useTranslation];\n});\n_c = Login;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Login);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"Login\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Login.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Navbar.tsx": -/*!****************************************!*\ - !*** ./frontend/components/Navbar.tsx ***! - \****************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router/dist/index.js\");\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router-dom/dist/index.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/Bars3Icon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/UserIcon.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\nvar Navbar = function Navbar(_ref) {\n _s();\n var isDarkMode = _ref.isDarkMode,\n toggleDarkMode = _ref.toggleDarkMode,\n currentUser = _ref.currentUser,\n setCurrentUser = _ref.setCurrentUser,\n isSidebarOpen = _ref.isSidebarOpen,\n setIsSidebarOpen = _ref.setIsSidebarOpen;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState2 = _slicedToArray(_useState, 2),\n isDropdownOpen = _useState2[0],\n setIsDropdownOpen = _useState2[1];\n var dropdownRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n var navigate = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_2__.useNavigate)();\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleClickOutside = function handleClickOutside(event) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {\n setIsDropdownOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", handleClickOutside);\n return function () {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, []);\n var toggleDropdown = function toggleDropdown() {\n setIsDropdownOpen(!isDropdownOpen);\n };\n var handleLogout = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var response;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.prev = 0;\n _context.next = 3;\n return fetch('/api/logout', {\n method: 'GET',\n credentials: 'include'\n });\n case 3:\n response = _context.sent;\n if (!response.ok) {\n _context.next = 9;\n break;\n }\n setCurrentUser(null);\n navigate('/login');\n _context.next = 14;\n break;\n case 9:\n _context.t0 = console;\n _context.next = 12;\n return response.json();\n case 12:\n _context.t1 = _context.sent;\n _context.t0.error.call(_context.t0, 'Logout failed:', _context.t1);\n case 14:\n _context.next = 19;\n break;\n case 16:\n _context.prev = 16;\n _context.t2 = _context[\"catch\"](0);\n console.error('Error during logout:', _context.t2);\n case 19:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[0, 16]]);\n }));\n return function handleLogout() {\n return _ref2.apply(this, arguments);\n };\n }();\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"nav\", {\n className: \"fixed top-0 left-0 right-0 z-50 bg-white dark:bg-gray-900 text-gray-900 dark:text-white shadow-md h-16\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"px-4 sm:px-6 lg:px-8 h-full flex items-center justify-between\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n return setIsSidebarOpen(!isSidebarOpen);\n },\n className: \"flex items-center focus:outline-none text-gray-500 dark:text-gray-500\",\n \"aria-label\": isSidebarOpen ? \"Collapse Sidebar\" : \"Expand Sidebar\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n className: \"h-6 mt-1 w-6 mr-2\"\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_4__.Link, {\n to: \"/\",\n className: \"flex items-center no-underline text-gray-900 dark:text-white\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"text-2xl font-bold\"\n }, \"tududi\"))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center space-x-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"relative\",\n ref: dropdownRef\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: toggleDropdown,\n className: \"flex items-center focus:outline-none\",\n \"aria-label\": \"User Menu\"\n }, currentUser !== null && currentUser !== void 0 && currentUser.avatarUrl ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"img\", {\n src: currentUser.avatarUrl,\n alt: \"User Avatar\",\n className: \"h-8 w-8 rounded-full object-cover border-2 border-green-500\"\n }) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"h-8 w-8 rounded-full border-2 border-green-500 bg-gray-200 dark:bg-gray-700 flex items-center justify-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n className: \"h-6 w-6 text-gray-500 dark:text-gray-300\"\n }))), isDropdownOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n ref: dropdownRef,\n className: \"absolute right-4 top-16 w-48 bg-white dark:bg-gray-800 rounded-md shadow-lg py-1 border border-gray-200 dark:border-gray-700\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_4__.Link, {\n to: \"/profile\",\n className: \"block px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700\",\n onClick: function onClick() {\n return setIsDropdownOpen(false);\n }\n }, t('nav.profile', 'Profile Settings')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n setIsDropdownOpen(false);\n handleLogout();\n },\n className: \"w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700\"\n }, t('nav.logout', 'Logout')))))));\n};\n_s(Navbar, \"oqYBwuFqzRGd6605389zYqHh9Rc=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation, react_router_dom__WEBPACK_IMPORTED_MODULE_2__.useNavigate];\n});\n_c = Navbar;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Navbar);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"Navbar\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Navbar.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Note/NoteDetails.tsx": -/*!**************************************************!*\ - !*** ./frontend/components/Note/NoteDetails.tsx ***! - \**************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router/dist/index.js\");\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router-dom/dist/index.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/DocumentTextIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/PencilSquareIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/TrashIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/TagIcon.js\");\n/* harmony import */ var _Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Shared/ConfirmDialog */ \"./frontend/components/Shared/ConfirmDialog.tsx\");\n/* harmony import */ var _NoteModal__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./NoteModal */ \"./frontend/components/Note/NoteModal.tsx\");\n/* harmony import */ var _utils_notesService__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../utils/notesService */ \"./frontend/utils/notesService.ts\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\n\nvar NoteDetails = function NoteDetails() {\n _s();\n var _useParams = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_4__.useParams)(),\n id = _useParams.id;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState2 = _slicedToArray(_useState, 2),\n note = _useState2[0],\n setNote = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState4 = _slicedToArray(_useState3, 2),\n isNoteModalOpen = _useState4[0],\n setIsNoteModalOpen = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState6 = _slicedToArray(_useState5, 2),\n isConfirmDialogOpen = _useState6[0],\n setIsConfirmDialogOpen = _useState6[1];\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState8 = _slicedToArray(_useState7, 2),\n noteToDelete = _useState8[0],\n setNoteToDelete = _useState8[1];\n var _useState9 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(true),\n _useState10 = _slicedToArray(_useState9, 2),\n isLoading = _useState10[0],\n setIsLoading = _useState10[1];\n var _useState11 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState12 = _slicedToArray(_useState11, 2),\n isError = _useState12[0],\n setIsError = _useState12[1];\n var navigate = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_4__.useNavigate)();\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var fetchNote = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var notes, foundNote;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.prev = 0;\n setIsLoading(true);\n _context.next = 4;\n return (0,_utils_notesService__WEBPACK_IMPORTED_MODULE_3__.fetchNotes)();\n case 4:\n notes = _context.sent;\n foundNote = notes.find(function (n) {\n return n.id === Number(id);\n });\n setNote(foundNote || null);\n if (!foundNote) {\n setIsError(true);\n }\n _context.next = 14;\n break;\n case 10:\n _context.prev = 10;\n _context.t0 = _context[\"catch\"](0);\n setIsError(true);\n console.error('Error fetching note:', _context.t0);\n case 14:\n _context.prev = 14;\n setIsLoading(false);\n return _context.finish(14);\n case 17:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[0, 10, 14, 17]]);\n }));\n return function fetchNote() {\n return _ref.apply(this, arguments);\n };\n }();\n fetchNote();\n }, [id]);\n var handleDeleteNote = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n if (noteToDelete) {\n _context2.next = 2;\n break;\n }\n return _context2.abrupt(\"return\");\n case 2:\n _context2.prev = 2;\n _context2.next = 5;\n return (0,_utils_notesService__WEBPACK_IMPORTED_MODULE_3__.deleteNote)(noteToDelete.id);\n case 5:\n navigate('/notes');\n _context2.next = 11;\n break;\n case 8:\n _context2.prev = 8;\n _context2.t0 = _context2[\"catch\"](2);\n console.error('Error deleting note:', _context2.t0);\n case 11:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, null, [[2, 8]]);\n }));\n return function handleDeleteNote() {\n return _ref2.apply(this, arguments);\n };\n }();\n var handleSaveNote = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(updatedNote) {\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n _context3.prev = 0;\n if (!(updatedNote.id !== undefined)) {\n _context3.next = 7;\n break;\n }\n _context3.next = 4;\n return (0,_utils_notesService__WEBPACK_IMPORTED_MODULE_3__.updateNote)(updatedNote.id, updatedNote);\n case 4:\n setNote(updatedNote);\n _context3.next = 8;\n break;\n case 7:\n console.error(\"Error: Note ID is undefined.\");\n case 8:\n _context3.next = 13;\n break;\n case 10:\n _context3.prev = 10;\n _context3.t0 = _context3[\"catch\"](0);\n console.error('Error saving note:', _context3.t0);\n case 13:\n setIsNoteModalOpen(false);\n case 14:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3, null, [[0, 10]]);\n }));\n return function handleSaveNote(_x) {\n return _ref3.apply(this, arguments);\n };\n }();\n var handleEditNote = function handleEditNote() {\n setIsNoteModalOpen(true);\n };\n var handleOpenConfirmDialog = function handleOpenConfirmDialog(note) {\n setNoteToDelete(note);\n setIsConfirmDialogOpen(true);\n };\n if (isLoading) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-center h-screen bg-gray-100 dark:bg-gray-900\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-xl font-semibold text-gray-700 dark:text-gray-200\"\n }, \"Loading note details...\"));\n }\n if (isError || !note) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-center h-screen bg-gray-100 dark:bg-gray-900\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-red-500 text-lg\"\n }, isError ? 'Error loading note details.' : 'Note not found.'));\n }\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex justify-center px-4 lg:px-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-full max-w-5xl\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-between mb-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n className: \"h-6 w-6 text-xl mr-2\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h2\", {\n className: \"text-2xl font-light text-gray-900 dark:text-gray-100\"\n }, note.title)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex space-x-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: handleEditNote,\n className: \"text-gray-500 hover:text-blue-700 dark:hover:text-blue-300 focus:outline-none\",\n \"aria-label\": \"Edit \".concat(note.title),\n title: \"Edit \".concat(note.title)\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n className: \"h-5 w-5\"\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n return handleOpenConfirmDialog(note);\n },\n className: \"text-gray-500 hover:text-red-700 dark:hover:text-red-300 focus:outline-none\",\n \"aria-label\": \"Delete \".concat(note.title),\n title: \"Delete \".concat(note.title)\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n className: \"h-5 w-5\"\n })))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"bg-white dark:bg-gray-900 shadow-md rounded-lg p-4 mb-6\"\n }, note.tags && note.tags.length > 0 && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mt-2 flex flex-wrap space-x-2\"\n }, note.tags.map(function (tag) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n key: tag.id,\n onClick: function onClick() {\n return navigate(\"/tasks?tag=\".concat(tag.name));\n },\n className: \"flex items-center space-x-1 px-2 py-1 bg-gray-100 dark:bg-gray-700 rounded-lg cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-600\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n className: \"h-4 w-4 text-gray-500 dark:text-gray-300\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"text-xs text-gray-700 dark:text-gray-300\"\n }, tag.name));\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-sm text-gray-500 dark:text-gray-400\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", null, \"Created on: \", new Date(note.created_at || '').toLocaleDateString()), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", null, \"Last updated: \", new Date(note.updated_at || '').toLocaleDateString())), note.project && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mt-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h3\", {\n className: \"text-lg font-semibold text-gray-900 dark:text-white\"\n }, \"Project\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_9__.Link, {\n to: \"/project/\".concat(note.project.id),\n className: \"text-blue-600 dark:text-blue-400 hover:underline\"\n }, note.project.name))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-6\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-gray-700 dark:text-gray-300 whitespace-pre-line\"\n }, note.content)), isNoteModalOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_NoteModal__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n isOpen: isNoteModalOpen,\n onClose: function onClose() {\n return setIsNoteModalOpen(false);\n },\n onSave: handleSaveNote,\n note: note\n }), isConfirmDialogOpen && noteToDelete && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n title: \"Delete Note\",\n message: \"Are you sure you want to delete the note \\\"\".concat(noteToDelete.title, \"\\\"?\"),\n onConfirm: handleDeleteNote,\n onCancel: function onCancel() {\n setIsConfirmDialogOpen(false);\n setNoteToDelete(null);\n }\n })));\n};\n_s(NoteDetails, \"bY6WeCnCUShZwa24FpTJ2U/5zyI=\", false, function () {\n return [react_router_dom__WEBPACK_IMPORTED_MODULE_4__.useParams, react_router_dom__WEBPACK_IMPORTED_MODULE_4__.useNavigate];\n});\n_c = NoteDetails;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (NoteDetails);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"NoteDetails\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Note/NoteDetails.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Note/NoteModal.tsx": -/*!************************************************!*\ - !*** ./frontend/components/Note/NoteModal.tsx ***! - \************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _Shared_ToastContext__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Shared/ToastContext */ \"./frontend/components/Shared/ToastContext.tsx\");\n/* harmony import */ var _Tag_TagInput__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Tag/TagInput */ \"./frontend/components/Tag/TagInput.tsx\");\n/* harmony import */ var _utils_tagsService__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../utils/tagsService */ \"./frontend/utils/tagsService.ts\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\nvar NoteModal = function NoteModal(_ref) {\n _s();\n var _note$tags;\n var isOpen = _ref.isOpen,\n onClose = _ref.onClose,\n note = _ref.note,\n onSave = _ref.onSave;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_4__.useTranslation)(),\n t = _useTranslation.t;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)({\n id: (note === null || note === void 0 ? void 0 : note.id) || 0,\n title: (note === null || note === void 0 ? void 0 : note.title) || '',\n content: (note === null || note === void 0 ? void 0 : note.content) || '',\n tags: (note === null || note === void 0 ? void 0 : note.tags) || []\n }),\n _useState2 = _slicedToArray(_useState, 2),\n formData = _useState2[0],\n setFormData = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)((note === null || note === void 0 || (_note$tags = note.tags) === null || _note$tags === void 0 ? void 0 : _note$tags.map(function (tag) {\n return tag.name;\n })) || []),\n _useState4 = _slicedToArray(_useState3, 2),\n tags = _useState4[0],\n setTags = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)([]),\n _useState6 = _slicedToArray(_useState5, 2),\n availableTags = _useState6[0],\n setAvailableTags = _useState6[1];\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState8 = _slicedToArray(_useState7, 2),\n error = _useState8[0],\n setError = _useState8[1];\n var modalRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n var _useState9 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState10 = _slicedToArray(_useState9, 2),\n isSubmitting = _useState10[0],\n setIsSubmitting = _useState10[1];\n var _useState11 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState12 = _slicedToArray(_useState11, 2),\n isClosing = _useState12[0],\n setIsClosing = _useState12[1];\n var _useToast = (0,_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_1__.useToast)(),\n showSuccessToast = _useToast.showSuccessToast,\n showErrorToast = _useToast.showErrorToast;\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var loadTags = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var data;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.prev = 0;\n _context.next = 3;\n return (0,_utils_tagsService__WEBPACK_IMPORTED_MODULE_3__.fetchTags)();\n case 3:\n data = _context.sent;\n setAvailableTags(data);\n _context.next = 11;\n break;\n case 7:\n _context.prev = 7;\n _context.t0 = _context[\"catch\"](0);\n console.error('Failed to fetch tags', _context.t0);\n showErrorToast(t('errors.failedToLoadTags'));\n case 11:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[0, 7]]);\n }));\n return function loadTags() {\n return _ref2.apply(this, arguments);\n };\n }();\n if (isOpen) {\n loadTags();\n }\n }, [isOpen, showErrorToast]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n if (isOpen) {\n var _note$tags2;\n // Extract tag names for display\n var tagNames = (note === null || note === void 0 || (_note$tags2 = note.tags) === null || _note$tags2 === void 0 ? void 0 : _note$tags2.map(function (tag) {\n return tag.name;\n })) || [];\n console.log(\"NoteModal received note with tags:\", note === null || note === void 0 ? void 0 : note.tags);\n console.log(\"Converted tag names:\", tagNames);\n setFormData({\n id: (note === null || note === void 0 ? void 0 : note.id) || 0,\n title: (note === null || note === void 0 ? void 0 : note.title) || '',\n content: (note === null || note === void 0 ? void 0 : note.content) || '',\n tags: (note === null || note === void 0 ? void 0 : note.tags) || []\n });\n setTags(tagNames);\n setError(null);\n }\n }, [isOpen, note]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleClickOutside = function handleClickOutside(event) {\n if (modalRef.current && !modalRef.current.contains(event.target)) {\n handleClose();\n }\n };\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n return function () {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [isOpen]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleKeyDown = function handleKeyDown(event) {\n if (event.key === 'Escape') {\n handleClose();\n }\n };\n if (isOpen) {\n document.addEventListener('keydown', handleKeyDown);\n }\n return function () {\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [isOpen]);\n var handleChange = function handleChange(e) {\n var _e$target = e.target,\n name = _e$target.name,\n value = _e$target.value;\n setFormData(function (prev) {\n return _objectSpread(_objectSpread({}, prev), {}, _defineProperty({}, name, value));\n });\n };\n var handleTagsChange = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(function (newTags) {\n console.log(\"NoteModal tags changed to:\", newTags);\n setTags(newTags);\n setFormData(function (prev) {\n return _objectSpread(_objectSpread({}, prev), {}, {\n tags: newTags.map(function (name) {\n return {\n name: name\n };\n })\n });\n });\n }, []);\n var handleSubmit = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {\n var noteTags, finalFormData;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n if (formData.title.trim()) {\n _context2.next = 3;\n break;\n }\n setError(t('errors.noteTitleRequired'));\n return _context2.abrupt(\"return\");\n case 3:\n setIsSubmitting(true);\n setError(null);\n _context2.prev = 5;\n // Convert string tags to tag objects\n noteTags = tags.map(function (tagName) {\n return {\n name: tagName\n };\n });\n console.log(\"Submitting note with tags array:\", tags);\n console.log(\"Converting to note tags:\", noteTags);\n\n // Create final form data with the tags\n finalFormData = _objectSpread(_objectSpread({}, formData), {}, {\n tags: noteTags\n });\n console.log(\"Final note data being saved:\", finalFormData);\n _context2.next = 13;\n return onSave(finalFormData);\n case 13:\n showSuccessToast(formData.id && formData.id !== 0 ? t('success.noteUpdated') : t('success.noteCreated'));\n handleClose();\n _context2.next = 21;\n break;\n case 17:\n _context2.prev = 17;\n _context2.t0 = _context2[\"catch\"](5);\n setError(_context2.t0.message);\n showErrorToast(t('errors.failedToSaveNote'));\n case 21:\n _context2.prev = 21;\n setIsSubmitting(false);\n return _context2.finish(21);\n case 24:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, null, [[5, 17, 21, 24]]);\n }));\n return function handleSubmit() {\n return _ref3.apply(this, arguments);\n };\n }();\n var handleClose = function handleClose() {\n setIsClosing(true);\n setTimeout(function () {\n onClose();\n setIsClosing(false);\n }, 300);\n };\n if (!isOpen) return null;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"fixed top-16 left-0 right-0 bottom-0 flex items-start sm:items-center justify-center bg-gray-900 bg-opacity-80 z-40 transition-opacity duration-300 \".concat(isClosing ? 'opacity-0' : 'opacity-100')\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n ref: modalRef,\n className: \"bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-800 sm:rounded-lg sm:shadow-2xl w-full sm:max-w-2xl overflow-hidden transform transition-transform duration-300 \".concat(isClosing ? 'scale-95' : 'scale-100', \" h-screen sm:h-auto flex flex-col\"),\n style: {\n maxHeight: 'calc(100vh - 4rem)'\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"form\", {\n className: \"flex flex-col flex-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"fieldset\", {\n className: \"flex flex-col flex-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"p-4 space-y-3 flex-1 text-sm overflow-y-auto\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"py-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"text\",\n id: \"noteTitle\",\n name: \"title\",\n value: formData.title,\n onChange: handleChange,\n required: true,\n className: \"block w-full text-xl font-semibold dark:bg-gray-800 text-black dark:text-white border-b-2 border-gray-200 dark:border-gray-900 focus:outline-none shadow-sm py-2\",\n placeholder: t('forms.noteTitlePlaceholder')\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"pb-3\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-xs font-medium text-gray-700 dark:text-gray-300 mb-2\"\n }, t('forms.tags'), \" \", tags.length > 0 ? \"(\".concat(tags.join(', '), \")\") : ''), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-full\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Tag_TagInput__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n onTagsChange: handleTagsChange,\n initialTags: tags,\n availableTags: availableTags\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"pb-3 flex-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-xs font-medium text-gray-700 dark:text-gray-300 mb-2\"\n }, t('forms.noteContent')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"textarea\", {\n id: \"noteContent\",\n name: \"content\",\n value: formData.content,\n onChange: handleChange,\n rows: 20,\n className: \"block w-full h-full rounded-md shadow-sm p-3 text-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 transition duration-150 ease-in-out\",\n placeholder: t('forms.noteContentPlaceholder')\n })), error && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-red-500\"\n }, error)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"p-3 flex-shrink-0 border-t border-gray-200 dark:border-gray-700 flex justify-end space-x-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: handleClose,\n className: \"px-4 py-2 text-md bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200 rounded-md hover:bg-gray-300 dark:hover:bg-gray-600 focus:outline-none transition duration-150 ease-in-out\"\n }, t('common.cancel')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: handleSubmit,\n disabled: isSubmitting,\n className: \"px-4 py-2 text-md bg-blue-600 text-white rounded-md hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 focus:outline-none transition duration-150 ease-in-out \".concat(isSubmitting ? 'opacity-50 cursor-not-allowed' : '')\n }, isSubmitting ? t('modals.submitting') : formData.id && formData.id !== 0 ? t('modals.updateNote') : t('modals.createNote')))))));\n};\n_s(NoteModal, \"nLSKPMz3W+W/a+fLfCrsKXSlG9c=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_4__.useTranslation, _Shared_ToastContext__WEBPACK_IMPORTED_MODULE_1__.useToast];\n});\n_c = NoteModal;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (NoteModal);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"NoteModal\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Note/NoteModal.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Notes.tsx": -/*!***************************************!*\ - !*** ./frontend/components/Notes.tsx ***! - \***************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router-dom/dist/index.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/BookOpenIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/MagnifyingGlassIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/PencilSquareIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/TrashIcon.js\");\n/* harmony import */ var _Note_NoteModal__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Note/NoteModal */ \"./frontend/components/Note/NoteModal.tsx\");\n/* harmony import */ var _Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Shared/ConfirmDialog */ \"./frontend/components/Shared/ConfirmDialog.tsx\");\n/* harmony import */ var _utils_notesService__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/notesService */ \"./frontend/utils/notesService.ts\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\n\n\nvar Notes = function Notes() {\n _s();\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)([]),\n _useState2 = _slicedToArray(_useState, 2),\n notes = _useState2[0],\n setNotes = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState4 = _slicedToArray(_useState3, 2),\n selectedNote = _useState4[0],\n setSelectedNote = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState6 = _slicedToArray(_useState5, 2),\n isNoteModalOpen = _useState6[0],\n setIsNoteModalOpen = _useState6[1];\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState8 = _slicedToArray(_useState7, 2),\n isConfirmDialogOpen = _useState8[0],\n setIsConfirmDialogOpen = _useState8[1];\n var _useState9 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState10 = _slicedToArray(_useState9, 2),\n noteToDelete = _useState10[0],\n setNoteToDelete = _useState10[1];\n var _useState11 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(''),\n _useState12 = _slicedToArray(_useState11, 2),\n searchQuery = _useState12[0],\n setSearchQuery = _useState12[1];\n var _useState13 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(true),\n _useState14 = _slicedToArray(_useState13, 2),\n isLoading = _useState14[0],\n setIsLoading = _useState14[1];\n var _useState15 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState16 = _slicedToArray(_useState15, 2),\n isError = _useState16[0],\n setIsError = _useState16[1];\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var loadNotes = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var fetchedNotes;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n setIsLoading(true);\n _context.prev = 1;\n _context.next = 4;\n return (0,_utils_notesService__WEBPACK_IMPORTED_MODULE_4__.fetchNotes)();\n case 4:\n fetchedNotes = _context.sent;\n setNotes(fetchedNotes);\n _context.next = 12;\n break;\n case 8:\n _context.prev = 8;\n _context.t0 = _context[\"catch\"](1);\n console.error('Error loading notes:', _context.t0);\n setIsError(true);\n case 12:\n _context.prev = 12;\n setIsLoading(false);\n return _context.finish(12);\n case 15:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[1, 8, 12, 15]]);\n }));\n return function loadNotes() {\n return _ref.apply(this, arguments);\n };\n }();\n loadNotes();\n }, []);\n var handleDeleteNote = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n if (noteToDelete) {\n _context2.next = 2;\n break;\n }\n return _context2.abrupt(\"return\");\n case 2:\n _context2.prev = 2;\n _context2.next = 5;\n return (0,_utils_notesService__WEBPACK_IMPORTED_MODULE_4__.deleteNote)(noteToDelete.id);\n case 5:\n setNotes(function (prev) {\n return prev.filter(function (note) {\n return note.id !== noteToDelete.id;\n });\n });\n setIsConfirmDialogOpen(false);\n setNoteToDelete(null);\n _context2.next = 13;\n break;\n case 10:\n _context2.prev = 10;\n _context2.t0 = _context2[\"catch\"](2);\n console.error('Error deleting note:', _context2.t0);\n case 13:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, null, [[2, 10]]);\n }));\n return function handleDeleteNote() {\n return _ref2.apply(this, arguments);\n };\n }();\n var handleEditNote = function handleEditNote(note) {\n setSelectedNote(note);\n setIsNoteModalOpen(true);\n };\n var handleSaveNote = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(noteData) {\n var updatedNotes, newNote;\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n _context3.prev = 0;\n if (!noteData.id) {\n _context3.next = 7;\n break;\n }\n _context3.next = 4;\n return (0,_utils_notesService__WEBPACK_IMPORTED_MODULE_4__.updateNote)(noteData.id, noteData);\n case 4:\n updatedNotes = notes.map(function (note) {\n return note.id === noteData.id ? noteData : note;\n });\n _context3.next = 11;\n break;\n case 7:\n _context3.next = 9;\n return (0,_utils_notesService__WEBPACK_IMPORTED_MODULE_4__.createNote)(noteData);\n case 9:\n newNote = _context3.sent;\n updatedNotes = [].concat(_toConsumableArray(notes), [newNote]);\n case 11:\n setNotes(updatedNotes);\n setIsNoteModalOpen(false);\n setSelectedNote(null);\n _context3.next = 19;\n break;\n case 16:\n _context3.prev = 16;\n _context3.t0 = _context3[\"catch\"](0);\n console.error('Error saving note:', _context3.t0);\n case 19:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3, null, [[0, 16]]);\n }));\n return function handleSaveNote(_x) {\n return _ref3.apply(this, arguments);\n };\n }();\n var filteredNotes = notes.filter(function (note) {\n return note.title.toLowerCase().includes(searchQuery.toLowerCase()) || note.content.toLowerCase().includes(searchQuery.toLowerCase());\n });\n if (isLoading) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-center h-screen bg-gray-100 dark:bg-gray-900\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-xl font-semibold text-gray-700 dark:text-gray-200\"\n }, t('notes.loading')));\n }\n if (isError) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-center h-screen bg-gray-100 dark:bg-gray-900\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-red-500 text-lg\"\n }, t('notes.error')));\n }\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex justify-center px-4 lg:px-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-full max-w-5xl\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-between mb-8\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n className: \"h-6 w-6 mr-2 text-gray-900 dark:text-white\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h2\", {\n className: \"text-2xl font-light text-gray-900 dark:text-white\"\n }, t('notes.title')))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-md shadow-sm p-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n className: \"h-5 w-5 text-gray-500 dark:text-gray-400 mr-2\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"text\",\n placeholder: t('notes.searchPlaceholder'),\n value: searchQuery,\n onChange: function onChange(e) {\n return setSearchQuery(e.target.value);\n },\n className: \"w-full bg-transparent border-none focus:ring-0 focus:outline-none dark:text-white\"\n }))), filteredNotes.length === 0 ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-gray-700 dark:text-gray-300\"\n }, t('notes.noNotesFound')) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"ul\", {\n className: \"space-y-1\"\n }, filteredNotes.map(function (note) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"li\", {\n key: note.id,\n className: \"bg-white dark:bg-gray-900 shadow rounded-lg px-4 py-2 flex justify-between items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex-grow overflow-hidden pr-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_7__.Link, {\n to: \"/note/\".concat(note.id),\n className: \"text-md font-semibold text-gray-900 dark:text-gray-100 hover:underline block\"\n }, note.title)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex space-x-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n return handleEditNote(note);\n },\n className: \"text-gray-500 hover:text-blue-700 dark:hover:text-blue-300 focus:outline-none\",\n \"aria-label\": t('notes.editNoteAriaLabel', {\n noteTitle: note.title\n }),\n title: t('notes.editNoteTitle', {\n noteTitle: note.title\n })\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n className: \"h-5 w-5\"\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n setNoteToDelete(note);\n setIsConfirmDialogOpen(true);\n },\n \"aria-label\": t('notes.deleteNoteAriaLabel', {\n noteTitle: note.title\n }),\n title: t('notes.deleteNoteTitle', {\n noteTitle: note.title\n })\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_9__[\"default\"], {\n className: \"h-5 w-5\"\n }))));\n })), isNoteModalOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Note_NoteModal__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n isOpen: isNoteModalOpen,\n onClose: function onClose() {\n return setIsNoteModalOpen(false);\n },\n onSave: handleSaveNote,\n note: selectedNote\n }), isConfirmDialogOpen && noteToDelete && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n title: t('modals.deleteNote.title'),\n message: t('modals.deleteNote.message', {\n noteTitle: noteToDelete.title\n }),\n onConfirm: handleDeleteNote,\n onCancel: function onCancel() {\n return setIsConfirmDialogOpen(false);\n }\n })));\n};\n_s(Notes, \"tWC9YyTMFcF80mPrda99BjZZhBw=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c = Notes;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Notes);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"Notes\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Notes.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Profile/ProfileSettings.tsx": -/*!*********************************************************!*\ - !*** ./frontend/components/Profile/ProfileSettings.tsx ***! - \*********************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/InformationCircleIcon.js\");\n/* harmony import */ var _Shared_ToastContext__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Shared/ToastContext */ \"./frontend/components/Shared/ToastContext.tsx\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n// Helper functions\nvar capitalize = function capitalize(str) {\n if (!str) return '';\n return str.charAt(0).toUpperCase() + str.slice(1);\n};\n\n// Format frequency for display\nvar formatFrequency = function formatFrequency(frequency) {\n if (frequency.endsWith('h')) {\n var value = frequency.replace('h', '');\n return \"\".concat(value, \" \").concat(parseInt(value) === 1 ? 'hour' : 'hours');\n } else if (frequency === 'daily') {\n return '1 day';\n } else if (frequency === 'weekly') {\n return '1 week';\n } else if (frequency === 'weekdays') {\n return 'Weekdays';\n }\n return frequency;\n};\n\n/**\n * ProfileSettings Component\n * Displays and manages user profile settings including appearance, language,\n * timezone, telegram integration, and task summary settings.\n */\nvar ProfileSettings = function ProfileSettings(_ref) {\n _s();\n var currentUser = _ref.currentUser,\n isDarkMode = _ref.isDarkMode,\n toggleDarkMode = _ref.toggleDarkMode;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t,\n i18n = _useTranslation.i18n;\n var _useToast = (0,_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_2__.useToast)(),\n showSuccessToast = _useToast.showSuccessToast,\n showErrorToast = _useToast.showErrorToast;\n\n // State variables\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState2 = _slicedToArray(_useState, 2),\n profile = _useState2[0],\n setProfile = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)({\n appearance: isDarkMode ? 'dark' : 'light',\n language: 'en',\n timezone: 'UTC',\n avatar_image: '',\n telegram_bot_token: ''\n }),\n _useState4 = _slicedToArray(_useState3, 2),\n formData = _useState4[0],\n setFormData = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(true),\n _useState6 = _slicedToArray(_useState5, 2),\n loading = _useState6[0],\n setLoading = _useState6[1];\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState8 = _slicedToArray(_useState7, 2),\n error = _useState8[0],\n setError = _useState8[1];\n var _useState9 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState10 = _slicedToArray(_useState9, 2),\n success = _useState10[0],\n setSuccess = _useState10[1];\n var _useState11 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(0),\n _useState12 = _slicedToArray(_useState11, 2),\n updateKey = _useState12[0],\n setUpdateKey = _useState12[1];\n var _useState13 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState14 = _slicedToArray(_useState13, 2),\n isChangingLanguage = _useState14[0],\n setIsChangingLanguage = _useState14[1];\n var _useState15 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(''),\n _useState16 = _slicedToArray(_useState15, 2),\n telegramBotToken = _useState16[0],\n setTelegramBotToken = _useState16[1];\n var _useState17 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(''),\n _useState18 = _slicedToArray(_useState17, 2),\n telegramChatId = _useState18[0],\n setTelegramChatId = _useState18[1];\n var _useState19 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState20 = _slicedToArray(_useState19, 2),\n isTesting = _useState20[0],\n setIsTesting = _useState20[1];\n var _useState21 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState22 = _slicedToArray(_useState21, 2),\n isSendingSummary = _useState22[0],\n setIsSendingSummary = _useState22[1];\n var _useState23 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState24 = _slicedToArray(_useState23, 2),\n schedulerStatus = _useState24[0],\n setSchedulerStatus = _useState24[1];\n var _useState25 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState26 = _slicedToArray(_useState25, 2),\n loadingStatus = _useState26[0],\n setLoadingStatus = _useState26[1];\n var _useState27 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState28 = _slicedToArray(_useState27, 2),\n isPolling = _useState28[0],\n setIsPolling = _useState28[1];\n var _useState29 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)('idle'),\n _useState30 = _slicedToArray(_useState29, 2),\n telegramSetupStatus = _useState30[0],\n setTelegramSetupStatus = _useState30[1];\n var _useState31 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState32 = _slicedToArray(_useState31, 2),\n telegramError = _useState32[0],\n setTelegramError = _useState32[1];\n var _useState33 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState34 = _slicedToArray(_useState33, 2),\n telegramBotInfo = _useState34[0],\n setTelegramBotInfo = _useState34[1];\n\n // Force update function for language changes\n var forceUpdate = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(function () {\n setUpdateKey(function (prevKey) {\n return prevKey + 1;\n });\n }, []);\n\n // Fetch scheduler status data\n var fetchSchedulerStatus = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var response, data;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.prev = 0;\n setLoadingStatus(true);\n _context.next = 4;\n return fetch('/api/profile/task-summary/status');\n case 4:\n response = _context.sent;\n if (response.ok) {\n _context.next = 7;\n break;\n }\n throw new Error(t('profile.statusFetchError', 'Failed to fetch scheduler status.'));\n case 7:\n _context.next = 9;\n return response.json();\n case 9:\n data = _context.sent;\n setSchedulerStatus(data);\n _context.next = 16;\n break;\n case 13:\n _context.prev = 13;\n _context.t0 = _context[\"catch\"](0);\n showErrorToast(_context.t0.message);\n case 16:\n _context.prev = 16;\n setLoadingStatus(false);\n return _context.finish(16);\n case 19:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[0, 13, 16, 19]]);\n }));\n return function fetchSchedulerStatus() {\n return _ref2.apply(this, arguments);\n };\n }();\n\n // Send task summary now\n var handleSendTaskSummaryNow = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {\n var response, _data, data;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n _context2.prev = 0;\n setIsSendingSummary(true);\n _context2.next = 4;\n return fetch('/api/profile/task-summary/send-now', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n case 4:\n response = _context2.sent;\n if (response.ok) {\n _context2.next = 10;\n break;\n }\n _context2.next = 8;\n return response.json();\n case 8:\n _data = _context2.sent;\n throw new Error(_data.error || t('profile.sendSummaryFailed', 'Failed to send summary.'));\n case 10:\n _context2.next = 12;\n return response.json();\n case 12:\n data = _context2.sent;\n showSuccessToast(data.message);\n\n // Fetch the updated scheduler status if enabled\n if (data.enabled) {\n fetchSchedulerStatus();\n }\n _context2.next = 20;\n break;\n case 17:\n _context2.prev = 17;\n _context2.t0 = _context2[\"catch\"](0);\n showErrorToast(_context2.t0.message);\n case 20:\n _context2.prev = 20;\n setIsSendingSummary(false);\n return _context2.finish(20);\n case 23:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, null, [[0, 17, 20, 23]]);\n }));\n return function handleSendTaskSummaryNow() {\n return _ref3.apply(this, arguments);\n };\n }();\n\n // Handle form field changes\n var handleChange = function handleChange(e) {\n var _e$target = e.target,\n name = _e$target.name,\n value = _e$target.value;\n setFormData(function (prev) {\n return _objectSpread(_objectSpread({}, prev), {}, _defineProperty({}, name, value));\n });\n\n // Handle appearance change immediately\n if (name === 'appearance' && toggleDarkMode) {\n var shouldBeDark = value === 'dark';\n if (shouldBeDark !== isDarkMode) {\n toggleDarkMode();\n }\n }\n\n // Handle language change immediately\n if (name === 'language' && value !== i18n.language) {\n handleLanguageChange(value);\n }\n };\n var handleLanguageChange = /*#__PURE__*/function () {\n var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(value) {\n var resources, loadPath, response, data;\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n _context3.prev = 0;\n setIsChangingLanguage(true);\n console.log(\"Changing language to: \".concat(value));\n\n // Change the i18n language\n _context3.next = 5;\n return i18n.changeLanguage(value);\n case 5:\n // Explicitly force the document's lang attribute to match\n document.documentElement.lang = value;\n\n // Verify translations are loaded\n resources = i18n.getResourceBundle(value, 'translation');\n console.log('Resources loaded for language:', value, resources ? 'Yes' : 'No');\n if (!(!resources || Object.keys(resources).length === 0)) {\n _context3.next = 27;\n break;\n }\n console.warn('Translations might not be fully loaded for:', value);\n\n // Try to load translations manually if needed\n loadPath = \"/locales/\".concat(value, \"/translation.json\");\n _context3.prev = 11;\n _context3.next = 14;\n return fetch(loadPath);\n case 14:\n response = _context3.sent;\n if (!response.ok) {\n _context3.next = 22;\n break;\n }\n _context3.next = 18;\n return response.json();\n case 18:\n data = _context3.sent;\n i18n.addResourceBundle(value, 'translation', data, true, true);\n console.log('Manually loaded translations for:', value);\n\n // Force app to recognize new translations\n if (window.forceLanguageReload) {\n window.forceLanguageReload(value);\n }\n case 22:\n _context3.next = 27;\n break;\n case 24:\n _context3.prev = 24;\n _context3.t0 = _context3[\"catch\"](11);\n console.error('Failed to manually load translations:', _context3.t0);\n case 27:\n // Force another update to ensure UI reflects new language\n setTimeout(function () {\n forceUpdate();\n\n // Try to load translations again if they still aren't available\n var checkAndLoadResources = i18n.getResourceBundle(value, 'translation');\n if (!checkAndLoadResources || Object.keys(checkAndLoadResources).length === 0) {\n console.warn('Still no translations after initial load, forcing reload');\n if (window.forceLanguageReload) {\n window.forceLanguageReload(value);\n }\n }\n\n // If change event wasn't fired, mark as complete after a delay\n setTimeout(function () {\n if (isChangingLanguage) {\n setIsChangingLanguage(false);\n }\n }, 800); // Longer timeout to ensure translations load\n }, 200);\n _context3.next = 34;\n break;\n case 30:\n _context3.prev = 30;\n _context3.t1 = _context3[\"catch\"](0);\n console.error('Error changing language:', _context3.t1);\n setIsChangingLanguage(false);\n case 34:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3, null, [[0, 30], [11, 24]]);\n }));\n return function handleLanguageChange(_x) {\n return _ref4.apply(this, arguments);\n };\n }();\n\n // Fetch profile data when component mounts\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var fetchProfile = /*#__PURE__*/function () {\n var _ref5 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {\n var response, data;\n return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n while (1) switch (_context4.prev = _context4.next) {\n case 0:\n _context4.prev = 0;\n setLoading(true);\n _context4.next = 4;\n return fetch('/api/profile');\n case 4:\n response = _context4.sent;\n if (response.ok) {\n _context4.next = 7;\n break;\n }\n throw new Error(t('profile.fetchError', 'Failed to fetch profile data.'));\n case 7:\n _context4.next = 9;\n return response.json();\n case 9:\n data = _context4.sent;\n setProfile(data);\n setFormData({\n appearance: isDarkMode ? 'dark' : 'light',\n // Use current app state instead of saved preference\n language: data.language || 'en',\n timezone: data.timezone || 'UTC',\n avatar_image: data.avatar_image || '',\n telegram_bot_token: data.telegram_bot_token || ''\n });\n setTelegramBotToken(data.telegram_bot_token || '');\n setTelegramChatId(data.telegram_chat_id || '');\n\n // Fetch scheduler status if task summaries are enabled\n if (data.task_summary_enabled) {\n fetchSchedulerStatus();\n }\n\n // If user has a token, check polling status\n if (data.telegram_bot_token) {\n fetchPollingStatus();\n }\n _context4.next = 21;\n break;\n case 18:\n _context4.prev = 18;\n _context4.t0 = _context4[\"catch\"](0);\n showErrorToast(_context4.t0.message);\n case 21:\n _context4.prev = 21;\n setLoading(false);\n return _context4.finish(21);\n case 24:\n case \"end\":\n return _context4.stop();\n }\n }, _callee4, null, [[0, 18, 21, 24]]);\n }));\n return function fetchProfile() {\n return _ref5.apply(this, arguments);\n };\n }();\n var fetchPollingStatus = /*#__PURE__*/function () {\n var _ref6 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee5() {\n var response, data;\n return _regeneratorRuntime().wrap(function _callee5$(_context5) {\n while (1) switch (_context5.prev = _context5.next) {\n case 0:\n _context5.prev = 0;\n _context5.next = 3;\n return fetch('/api/telegram/polling-status');\n case 3:\n response = _context5.sent;\n if (response.ok) {\n _context5.next = 6;\n break;\n }\n throw new Error(t('profile.pollingStatusError', 'Failed to fetch polling status.'));\n case 6:\n _context5.next = 8;\n return response.json();\n case 8:\n data = _context5.sent;\n setIsPolling(data.running);\n\n // If bot token exists but polling is not active, start polling automatically\n if (data.token_exists && !data.running) {\n console.log('Telegram bot token exists but polling not active. Starting polling automatically...');\n handleStartPolling();\n }\n _context5.next = 16;\n break;\n case 13:\n _context5.prev = 13;\n _context5.t0 = _context5[\"catch\"](0);\n console.error('Error fetching polling status:', _context5.t0);\n case 16:\n case \"end\":\n return _context5.stop();\n }\n }, _callee5, null, [[0, 13]]);\n }));\n return function fetchPollingStatus() {\n return _ref6.apply(this, arguments);\n };\n }();\n fetchProfile();\n }, []);\n\n // Add an effect to monitor language changes\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n console.log(\"Component refreshed with key: \".concat(updateKey, \", language: \").concat(i18n.language));\n }, [updateKey, i18n.language]);\n\n // Update appearance in form data when dark mode changes\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n setFormData(function (prev) {\n return _objectSpread(_objectSpread({}, prev), {}, {\n appearance: isDarkMode ? 'dark' : 'light'\n });\n });\n }, [isDarkMode]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleLanguageChanged = function handleLanguageChanged(lng) {\n console.log(\"Language changed to \".concat(lng));\n // Force component to re-render when language changes\n forceUpdate();\n };\n\n // Handler for the custom app-language-changed event\n var handleAppLanguageChanged = function handleAppLanguageChanged(event) {\n console.log('Custom language change event received:', event.detail.language);\n // Force an update to re-render with new translations\n forceUpdate();\n // Mark language change as complete after a short delay\n // This ensures the UI has time to update with new translations\n setTimeout(function () {\n setIsChangingLanguage(false);\n }, 300);\n };\n\n // Add language change listeners\n i18n.on('languageChanged', handleLanguageChanged);\n window.addEventListener('app-language-changed', handleAppLanguageChanged);\n\n // Clean up listeners on unmount\n return function () {\n i18n.off('languageChanged', handleLanguageChanged);\n window.removeEventListener('app-language-changed', handleAppLanguageChanged);\n };\n }, []);\n var handleSetupTelegram = /*#__PURE__*/function () {\n var _ref7 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee6() {\n var _data$bot, response, _data2, data, _data$bot$polling_sta, botUsername;\n return _regeneratorRuntime().wrap(function _callee6$(_context6) {\n while (1) switch (_context6.prev = _context6.next) {\n case 0:\n setTelegramSetupStatus('loading');\n setTelegramError(null);\n setTelegramBotInfo(null);\n _context6.prev = 3;\n if (!(!formData.telegram_bot_token || !formData.telegram_bot_token.includes(':'))) {\n _context6.next = 6;\n break;\n }\n throw new Error(t('profile.invalidTelegramToken'));\n case 6:\n _context6.next = 8;\n return fetch('/api/telegram/setup', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n token: formData.telegram_bot_token\n })\n });\n case 8:\n response = _context6.sent;\n if (response.ok) {\n _context6.next = 14;\n break;\n }\n _context6.next = 12;\n return response.json();\n case 12:\n _data2 = _context6.sent;\n throw new Error(_data2.error || t('profile.telegramSetupFailed'));\n case 14:\n _context6.next = 16;\n return response.json();\n case 16:\n data = _context6.sent;\n setTelegramSetupStatus('success');\n setSuccess(t('profile.telegramSetupSuccess'));\n\n // Save bot info for display\n if (data.bot) {\n setTelegramBotInfo(data.bot);\n setIsPolling(true);\n\n // Explicitly verify polling is started\n if (!((_data$bot$polling_sta = data.bot.polling_status) !== null && _data$bot$polling_sta !== void 0 && _data$bot$polling_sta.running)) {\n console.log('Polling not started automatically during setup. Starting manually...');\n // Small delay to ensure the server has registered the token\n setTimeout(function () {\n handleStartPolling();\n }, 1000);\n }\n }\n\n // Format the URL to start the bot chat\n botUsername = ((_data$bot = data.bot) === null || _data$bot === void 0 ? void 0 : _data$bot.username) || formData.telegram_bot_token.split(':')[0]; // Open the Telegram bot chat in a new window\n window.open(\"https://t.me/\".concat(botUsername), '_blank');\n _context6.next = 29;\n break;\n case 24:\n _context6.prev = 24;\n _context6.t0 = _context6[\"catch\"](3);\n console.error('Telegram setup error:', _context6.t0);\n setTelegramSetupStatus('error');\n setTelegramError(_context6.t0.message);\n case 29:\n case \"end\":\n return _context6.stop();\n }\n }, _callee6, null, [[3, 24]]);\n }));\n return function handleSetupTelegram() {\n return _ref7.apply(this, arguments);\n };\n }();\n var handleStartPolling = /*#__PURE__*/function () {\n var _ref8 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee7() {\n var response, _data3, data;\n return _regeneratorRuntime().wrap(function _callee7$(_context7) {\n while (1) switch (_context7.prev = _context7.next) {\n case 0:\n _context7.prev = 0;\n _context7.next = 3;\n return fetch('/api/telegram/start-polling', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n case 3:\n response = _context7.sent;\n if (response.ok) {\n _context7.next = 9;\n break;\n }\n _context7.next = 7;\n return response.json();\n case 7:\n _data3 = _context7.sent;\n throw new Error(_data3.error || t('profile.startPollingFailed'));\n case 9:\n _context7.next = 11;\n return response.json();\n case 11:\n data = _context7.sent;\n setIsPolling(true);\n showSuccessToast(t('profile.pollingStarted'));\n\n // Update bot info if available\n if (telegramBotInfo) {\n setTelegramBotInfo(_objectSpread(_objectSpread({}, telegramBotInfo), {}, {\n polling_status: data.status\n }));\n }\n _context7.next = 21;\n break;\n case 17:\n _context7.prev = 17;\n _context7.t0 = _context7[\"catch\"](0);\n console.error('Start polling error:', _context7.t0);\n showErrorToast(t('profile.pollingError'));\n case 21:\n case \"end\":\n return _context7.stop();\n }\n }, _callee7, null, [[0, 17]]);\n }));\n return function handleStartPolling() {\n return _ref8.apply(this, arguments);\n };\n }();\n var handleStopPolling = /*#__PURE__*/function () {\n var _ref9 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee8() {\n var response, _data4, data;\n return _regeneratorRuntime().wrap(function _callee8$(_context8) {\n while (1) switch (_context8.prev = _context8.next) {\n case 0:\n _context8.prev = 0;\n _context8.next = 3;\n return fetch('/api/telegram/stop-polling', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n case 3:\n response = _context8.sent;\n if (response.ok) {\n _context8.next = 9;\n break;\n }\n _context8.next = 7;\n return response.json();\n case 7:\n _data4 = _context8.sent;\n throw new Error(_data4.error || t('profile.stopPollingFailed'));\n case 9:\n _context8.next = 11;\n return response.json();\n case 11:\n data = _context8.sent;\n setIsPolling(false);\n showSuccessToast(t('profile.pollingStopped', 'Polling stopped successfully.'));\n\n // Update bot info if available\n if (telegramBotInfo) {\n setTelegramBotInfo(_objectSpread(_objectSpread({}, telegramBotInfo), {}, {\n polling_status: data.status\n }));\n }\n _context8.next = 21;\n break;\n case 17:\n _context8.prev = 17;\n _context8.t0 = _context8[\"catch\"](0);\n console.error('Stop polling error:', _context8.t0);\n showErrorToast(t('profile.pollingError'));\n case 21:\n case \"end\":\n return _context8.stop();\n }\n }, _callee8, null, [[0, 17]]);\n }));\n return function handleStopPolling() {\n return _ref9.apply(this, arguments);\n };\n }();\n var handleSubmit = /*#__PURE__*/function () {\n var _ref10 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee9(e) {\n var response, data, updatedProfile;\n return _regeneratorRuntime().wrap(function _callee9$(_context9) {\n while (1) switch (_context9.prev = _context9.next) {\n case 0:\n e.preventDefault();\n setError(null);\n setSuccess(null);\n _context9.prev = 3;\n _context9.next = 6;\n return fetch('/api/profile', {\n method: 'PATCH',\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json'\n },\n body: JSON.stringify(formData)\n });\n case 6:\n response = _context9.sent;\n if (response.ok) {\n _context9.next = 12;\n break;\n }\n _context9.next = 10;\n return response.json();\n case 10:\n data = _context9.sent;\n throw new Error(data.error || 'Failed to update profile.');\n case 12:\n _context9.next = 14;\n return response.json();\n case 14:\n updatedProfile = _context9.sent;\n setProfile(updatedProfile);\n\n // Make sure to update language if it was changed\n if (!(updatedProfile.language !== i18n.language)) {\n _context9.next = 20;\n break;\n }\n console.log('Updating language after form submission:', updatedProfile.language);\n _context9.next = 20;\n return i18n.changeLanguage(updatedProfile.language);\n case 20:\n setSuccess(t('profile.successMessage'));\n _context9.next = 26;\n break;\n case 23:\n _context9.prev = 23;\n _context9.t0 = _context9[\"catch\"](3);\n setError(_context9.t0.message);\n case 26:\n case \"end\":\n return _context9.stop();\n }\n }, _callee9, null, [[3, 23]]);\n }));\n return function handleSubmit(_x2) {\n return _ref10.apply(this, arguments);\n };\n }();\n if (loading) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-center h-screen bg-gray-100 dark:bg-gray-900\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-xl font-semibold text-gray-700 dark:text-gray-200\"\n }, t('common.loading')));\n }\n if (error) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-center h-screen bg-gray-100 dark:bg-gray-900\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-red-500 text-lg\"\n }, error));\n }\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"max-w-5xl mx-auto p-6\",\n key: \"profile-settings-\".concat(updateKey)\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h2\", {\n className: \"text-2xl font-semibold text-gray-900 dark:text-white mb-6\"\n }, t('profile.title')), success && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4 text-green-500\"\n }, success), error && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4 text-red-500\"\n }, error), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"form\", {\n onSubmit: handleSubmit\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-sm font-medium text-gray-700 dark:text-gray-300\"\n }, t('profile.appearance')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"select\", {\n name: \"appearance\",\n value: formData.appearance,\n onChange: handleChange,\n className: \"mt-1 block w-full border border-gray-300 dark:border-gray-700 rounded-md shadow-sm px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"light\"\n }, t('profile.lightMode', 'Light')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"dark\"\n }, t('profile.darkMode', 'Dark')))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-sm font-medium text-gray-700 dark:text-gray-300\"\n }, t('profile.language')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"select\", {\n name: \"language\",\n value: formData.language,\n onChange: handleChange,\n className: \"mt-1 block w-full border border-gray-300 dark:border-gray-700 rounded-md shadow-sm px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"en\"\n }, t('profile.english')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"es\"\n }, t('profile.spanish')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"el\"\n }, t('profile.greek')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"jp\"\n }, t('profile.japanese')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"ua\"\n }, t('profile.ukrainian')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"de\"\n }, t('profile.deutsch'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"mt-2 text-xs text-gray-500 dark:text-gray-400\"\n }, t('profile.languageChangedNote', 'Language changes are applied immediately')), isChangingLanguage && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mt-2 text-sm text-blue-500 animate-pulse\"\n }, t('profile.languageChanging', 'Changing language...'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-sm font-medium text-gray-700 dark:text-gray-300\"\n }, t('profile.timezone')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"select\", {\n name: \"timezone\",\n value: formData.timezone,\n onChange: handleChange,\n className: \"mt-1 block w-full border border-gray-300 dark:border-gray-700 rounded-md shadow-sm px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"UTC\"\n }, \"UTC\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"America/New_York\"\n }, \"America/New_York\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"Europe/London\"\n }, \"Europe/London\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"Asia/Tokyo\"\n }, \"Asia/Tokyo\"))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-6 p-4 bg-gray-50 dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h3\", {\n className: \"text-lg font-medium text-gray-900 dark:text-white mb-3\"\n }, t('profile.telegramIntegration', 'Telegram Integration')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4 text-sm text-gray-600 dark:text-gray-300 flex items-start\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n className: \"h-5 w-5 mr-2 flex-shrink-0 text-blue-500\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", null, t('profile.telegramDescription', 'Connect your Tududi account to a Telegram bot to add items to your inbox via Telegram messages.'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-sm font-medium text-gray-700 dark:text-gray-300\"\n }, t('profile.telegramBotToken', 'Telegram Bot Token')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"text\",\n name: \"telegram_bot_token\",\n value: formData.telegram_bot_token || '',\n onChange: handleChange,\n placeholder: \"123456789:ABCDefGhIJKlmNoPQRsTUVwxyZ\",\n className: \"mt-1 block w-full border border-gray-300 dark:border-gray-700 rounded-md shadow-sm px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"mt-2 text-xs text-gray-500 dark:text-gray-400\"\n }, t('profile.telegramTokenDescription', 'Create a bot with @BotFather on Telegram and paste the token here.')), (profile === null || profile === void 0 ? void 0 : profile.telegram_chat_id) && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4 p-2 bg-green-50 dark:bg-green-900 border border-green-200 dark:border-green-800 rounded text-green-800 dark:text-green-200\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-sm\"\n }, t('profile.telegramConnected', 'Your Telegram account is connected! Send messages to your bot to add items to your Tududi inbox.'))), telegramError && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4 p-2 bg-red-50 dark:bg-red-900 border border-red-200 dark:border-red-800 rounded text-red-800 dark:text-red-200\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-sm\"\n }, telegramError)), telegramBotInfo && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4 p-2 bg-blue-50 dark:bg-blue-900 border border-blue-200 dark:border-blue-800 rounded text-blue-800 dark:text-blue-200\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"font-medium mb-2\"\n }, t('profile.botConfigured', 'Bot configured successfully!')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-sm space-y-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"font-semibold\"\n }, t('profile.botUsername', 'Bot Username:'), \" \"), \"@\", telegramBotInfo.username), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"font-semibold mb-1\"\n }, t('profile.pollingStatus', 'Polling Status:'), \" \"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center mb-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-3 h-3 rounded-full mr-2 \".concat(isPolling ? 'bg-green-500' : 'bg-red-500')\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", null, isPolling ? t('profile.pollingActive') : t('profile.pollingInactive'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-xs mb-2\"\n }, t('profile.pollingNote', 'Polling periodically checks for new messages from Telegram and adds them to your inbox.')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex flex-col sm:flex-row sm:items-center mt-2\"\n }, isPolling ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: handleStopPolling,\n className: \"px-3 py-1 bg-red-600 text-white dark:bg-red-700 rounded text-sm hover:bg-red-700 dark:hover:bg-red-800 text-center mb-2 sm:mb-0 sm:mr-3\"\n }, t('profile.stopPolling', 'Stop Polling')) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: handleStartPolling,\n className: \"px-3 py-1 bg-blue-600 text-white dark:bg-blue-700 rounded text-sm hover:bg-blue-700 dark:hover:bg-blue-800 text-center mb-2 sm:mb-0 sm:mr-3\"\n }, t('profile.startPolling', 'Start Polling')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"a\", {\n href: telegramBotInfo.chat_url,\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n className: \"px-3 py-1 bg-green-600 text-white dark:bg-green-700 rounded text-sm hover:bg-green-700 dark:hover:bg-green-800 text-center mb-2 sm:mb-0 sm:mr-3\"\n }, t('profile.openTelegram', 'Open in Telegram')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee10() {\n var testMessage, response, result;\n return _regeneratorRuntime().wrap(function _callee10$(_context10) {\n while (1) switch (_context10.prev = _context10.next) {\n case 0:\n _context10.prev = 0;\n testMessage = prompt('Enter a test message:');\n if (!testMessage) {\n _context10.next = 10;\n break;\n }\n _context10.next = 5;\n return fetch(\"/api/telegram/test/\".concat(profile === null || profile === void 0 ? void 0 : profile.id), {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n text: testMessage\n })\n });\n case 5:\n response = _context10.sent;\n _context10.next = 8;\n return response.json();\n case 8:\n result = _context10.sent;\n if (result.success) {\n showSuccessToast(t('profile.testMessageSent', 'Test message sent successfully!'));\n } else {\n showErrorToast(t('profile.testMessageFailed', 'Failed to send test message.'));\n }\n case 10:\n _context10.next = 16;\n break;\n case 12:\n _context10.prev = 12;\n _context10.t0 = _context10[\"catch\"](0);\n console.error('Test message error:', _context10.t0);\n showErrorToast(t('profile.testMessageError', 'Error sending test message.'));\n case 16:\n case \"end\":\n return _context10.stop();\n }\n }, _callee10, null, [[0, 12]]);\n })),\n className: \"px-3 py-1 bg-purple-600 text-white dark:bg-purple-700 rounded text-sm hover:bg-purple-700 dark:hover:bg-purple-800 text-center\"\n }, t('profile.testTelegramMessage', 'Test Telegram')))))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: handleSetupTelegram,\n disabled: !formData.telegram_bot_token || telegramSetupStatus === 'loading',\n className: \"px-4 py-2 rounded-md \".concat(!formData.telegram_bot_token || telegramSetupStatus === 'loading' ? 'bg-gray-300 dark:bg-gray-700 text-gray-500 dark:text-gray-400 cursor-not-allowed' : 'bg-blue-600 text-white hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600')\n }, telegramSetupStatus === 'loading' ? t('profile.settingUp', 'Setting up...') : t('profile.setupTelegram', 'Setup Telegram'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h3\", {\n className: \"text-lg font-medium text-gray-900 dark:text-white mb-3\"\n }, t('profile.taskSummaryNotifications', 'Task Summary Notifications')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4 text-sm text-gray-600 dark:text-gray-300 flex items-start\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n className: \"h-5 w-5 mr-2 flex-shrink-0 text-blue-500\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", null, t('profile.taskSummaryDescription', 'Receive regular summaries of your tasks via Telegram. This feature requires your Telegram integration to be set up.'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4 flex items-center justify-between\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"text-sm font-medium text-gray-700 dark:text-gray-300\"\n }, t('profile.enableTaskSummary', 'Enable Task Summaries')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"relative inline-block w-12 h-6 transition-colors duration-200 ease-in-out rounded-full cursor-pointer \".concat(profile !== null && profile !== void 0 && profile.task_summary_enabled ? 'bg-blue-500' : 'bg-gray-300 dark:bg-gray-600'),\n onClick: /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee11() {\n var response, _data5, data;\n return _regeneratorRuntime().wrap(function _callee11$(_context11) {\n while (1) switch (_context11.prev = _context11.next) {\n case 0:\n _context11.prev = 0;\n _context11.next = 3;\n return fetch('/api/profile/task-summary/toggle', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n case 3:\n response = _context11.sent;\n if (response.ok) {\n _context11.next = 9;\n break;\n }\n _context11.next = 7;\n return response.json();\n case 7:\n _data5 = _context11.sent;\n throw new Error(_data5.error || t('profile.toggleFailed'));\n case 9:\n _context11.next = 11;\n return response.json();\n case 11:\n data = _context11.sent;\n setProfile(function (prev) {\n return prev ? _objectSpread(_objectSpread({}, prev), {}, {\n task_summary_enabled: data.enabled\n }) : null;\n });\n showSuccessToast(data.message);\n _context11.next = 19;\n break;\n case 16:\n _context11.prev = 16;\n _context11.t0 = _context11[\"catch\"](0);\n showErrorToast(_context11.t0.message);\n case 19:\n case \"end\":\n return _context11.stop();\n }\n }, _callee11, null, [[0, 16]]);\n }))\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"absolute left-0 top-0 bottom-0 m-1 w-4 h-4 transition-transform duration-200 ease-in-out transform bg-white rounded-full \".concat(profile !== null && profile !== void 0 && profile.task_summary_enabled ? 'translate-x-6' : 'translate-x-0')\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2\"\n }, t('profile.summaryFrequency', 'Summary Frequency')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex flex-wrap gap-2\"\n }, ['1h', '2h', '4h', '8h', '12h', 'daily', 'weekly'].map(function (frequency) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n key: frequency,\n type: \"button\",\n className: \"px-3 py-1.5 text-sm rounded-full \".concat((profile === null || profile === void 0 ? void 0 : profile.task_summary_frequency) === frequency ? 'bg-blue-500 text-white' : 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300'),\n onClick: /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee12() {\n var response, _data6, data;\n return _regeneratorRuntime().wrap(function _callee12$(_context12) {\n while (1) switch (_context12.prev = _context12.next) {\n case 0:\n _context12.prev = 0;\n _context12.next = 3;\n return fetch('/api/profile/task-summary/frequency', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n frequency: frequency\n })\n });\n case 3:\n response = _context12.sent;\n if (response.ok) {\n _context12.next = 9;\n break;\n }\n _context12.next = 7;\n return response.json();\n case 7:\n _data6 = _context12.sent;\n throw new Error(_data6.error || t('profile.frequencyUpdateFailed'));\n case 9:\n _context12.next = 11;\n return response.json();\n case 11:\n data = _context12.sent;\n // Update the profile with the new frequency\n setProfile(function (prev) {\n return prev ? _objectSpread(_objectSpread({}, prev), {}, {\n task_summary_frequency: frequency\n }) : null;\n });\n showSuccessToast(data.message);\n _context12.next = 19;\n break;\n case 16:\n _context12.prev = 16;\n _context12.t0 = _context12[\"catch\"](0);\n showErrorToast(_context12.t0.message);\n case 19:\n case \"end\":\n return _context12.stop();\n }\n }, _callee12, null, [[0, 16]]);\n }))\n }, t(\"profile.frequency.\".concat(frequency), formatFrequency(frequency)));\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"mt-2 text-xs text-gray-500 dark:text-gray-400\"\n }, t('profile.frequencyHelp', 'Choose how often you want to receive task summaries.'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mt-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n disabled: !(profile !== null && profile !== void 0 && profile.telegram_bot_token) || !(profile !== null && profile !== void 0 && profile.telegram_chat_id),\n className: \"px-4 py-2 rounded-md \".concat(!(profile !== null && profile !== void 0 && profile.telegram_bot_token) || !(profile !== null && profile !== void 0 && profile.telegram_chat_id) ? 'bg-gray-300 dark:bg-gray-700 text-gray-500 dark:text-gray-400 cursor-not-allowed' : 'bg-blue-600 text-white hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600'),\n onClick: /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee13() {\n var response, _data7, data;\n return _regeneratorRuntime().wrap(function _callee13$(_context13) {\n while (1) switch (_context13.prev = _context13.next) {\n case 0:\n _context13.prev = 0;\n _context13.next = 3;\n return fetch('/api/profile/task-summary/send-now', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n case 3:\n response = _context13.sent;\n if (response.ok) {\n _context13.next = 9;\n break;\n }\n _context13.next = 7;\n return response.json();\n case 7:\n _data7 = _context13.sent;\n throw new Error(_data7.error || t('profile.sendSummaryFailed'));\n case 9:\n _context13.next = 11;\n return response.json();\n case 11:\n data = _context13.sent;\n showSuccessToast(data.message);\n _context13.next = 18;\n break;\n case 15:\n _context13.prev = 15;\n _context13.t0 = _context13[\"catch\"](0);\n showErrorToast(_context13.t0.message);\n case 18:\n case \"end\":\n return _context13.stop();\n }\n }, _callee13, null, [[0, 15]]);\n }))\n }, t('profile.sendTestSummary', 'Send Test Summary')), (!(profile !== null && profile !== void 0 && profile.telegram_bot_token) || !(profile !== null && profile !== void 0 && profile.telegram_chat_id)) && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"mt-2 text-xs text-red-500\"\n }, t('profile.telegramRequiredForSummaries', 'Telegram integration must be set up to use task summaries.')))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex justify-end\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"submit\",\n className: \"px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600\"\n }, t('profile.saveChanges')))));\n};\n_s(ProfileSettings, \"4Npd7QNMvIVHBLrp6ITLfb9zfrc=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation, _Shared_ToastContext__WEBPACK_IMPORTED_MODULE_2__.useToast];\n});\n_c = ProfileSettings;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ProfileSettings);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"ProfileSettings\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Profile/ProfileSettings.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Project/ProjectDetails.tsx": -/*!********************************************************!*\ - !*** ./frontend/components/Project/ProjectDetails.tsx ***! - \********************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router/dist/index.js\");\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router-dom/dist/index.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/FolderIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/PencilSquareIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/TrashIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/Squares2X2Icon.js\");\n/* harmony import */ var _Task_TaskList__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Task/TaskList */ \"./frontend/components/Task/TaskList.tsx\");\n/* harmony import */ var _Project_ProjectModal__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Project/ProjectModal */ \"./frontend/components/Project/ProjectModal.tsx\");\n/* harmony import */ var _Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Shared/ConfirmDialog */ \"./frontend/components/Shared/ConfirmDialog.tsx\");\n/* harmony import */ var _store_useStore__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../store/useStore */ \"./frontend/store/useStore.ts\");\n/* harmony import */ var _Task_NewTask__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../Task/NewTask */ \"./frontend/components/Task/NewTask.tsx\");\n/* harmony import */ var _utils_projectsService__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../utils/projectsService */ \"./frontend/utils/projectsService.ts\");\n/* harmony import */ var _utils_tasksService__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../utils/tasksService */ \"./frontend/utils/tasksService.ts\");\n/* harmony import */ var _utils_areasService__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../utils/areasService */ \"./frontend/utils/areasService.ts\");\n/* harmony import */ var _utils_authUtils__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../utils/authUtils */ \"./frontend/utils/authUtils.ts\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/CalendarDaysIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/InformationCircleIcon.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\n\n\n\n\n\n\n\n\nvar priorityStyles = {\n high: 'bg-red-500',\n medium: 'bg-yellow-500',\n low: 'bg-green-500',\n \"default\": 'bg-gray-400'\n};\nvar ProjectDetails = function ProjectDetails() {\n _s();\n var _useParams = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_10__.useParams)(),\n id = _useParams.id;\n var navigate = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_10__.useNavigate)();\n var areas = (0,_store_useStore__WEBPACK_IMPORTED_MODULE_4__.useStore)(function (state) {\n return state.areasStore.areas;\n });\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(undefined),\n _useState2 = _slicedToArray(_useState, 2),\n project = _useState2[0],\n setProject = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)([]),\n _useState4 = _slicedToArray(_useState3, 2),\n tasks = _useState4[0],\n setTasks = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(true),\n _useState6 = _slicedToArray(_useState5, 2),\n loading = _useState6[0],\n setLoading = _useState6[1];\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState8 = _slicedToArray(_useState7, 2),\n error = _useState8[0],\n setError = _useState8[1];\n var _useState9 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState10 = _slicedToArray(_useState9, 2),\n isModalOpen = _useState10[0],\n setIsModalOpen = _useState10[1];\n var _useState11 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState12 = _slicedToArray(_useState11, 2),\n isConfirmDialogOpen = _useState12[0],\n setIsConfirmDialogOpen = _useState12[1];\n var _useState13 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState14 = _slicedToArray(_useState13, 2),\n isCompletedOpen = _useState14[0],\n setIsCompletedOpen = _useState14[1];\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var loadProjectData = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var projectData;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n if (id) {\n _context.next = 3;\n break;\n }\n console.error(\"Project ID is missing.\");\n return _context.abrupt(\"return\");\n case 3:\n setLoading(true);\n _context.prev = 4;\n (0,_utils_areasService__WEBPACK_IMPORTED_MODULE_8__.fetchAreas)();\n _context.next = 8;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_6__.fetchProjectById)(id);\n case 8:\n projectData = _context.sent;\n setProject(projectData);\n setTasks(projectData.tasks || []);\n _context.next = 16;\n break;\n case 13:\n _context.prev = 13;\n _context.t0 = _context[\"catch\"](4);\n console.error(\"Error fetching project data:\", _context.t0);\n case 16:\n _context.prev = 16;\n setLoading(false);\n return _context.finish(16);\n case 19:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[4, 13, 16, 19]]);\n }));\n return function loadProjectData() {\n return _ref.apply(this, arguments);\n };\n }();\n loadProjectData();\n }, [id, _utils_areasService__WEBPACK_IMPORTED_MODULE_8__.fetchAreas]);\n var handleTaskCreate = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(taskName) {\n var newTask;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n if (project) {\n _context2.next = 3;\n break;\n }\n console.error(\"Cannot create task: Project is missing\");\n throw new Error(\"Cannot create task: Project is missing\");\n case 3:\n _context2.prev = 3;\n _context2.next = 6;\n return (0,_utils_tasksService__WEBPACK_IMPORTED_MODULE_7__.createTask)({\n name: taskName,\n status: \"not_started\",\n project_id: project.id\n });\n case 6:\n newTask = _context2.sent;\n setTasks(function (prevTasks) {\n return [].concat(_toConsumableArray(prevTasks), [newTask]);\n });\n _context2.next = 16;\n break;\n case 10:\n _context2.prev = 10;\n _context2.t0 = _context2[\"catch\"](3);\n console.error(\"Error creating task:\", _context2.t0);\n // Check if it's an authentication error\n if (!(0,_utils_authUtils__WEBPACK_IMPORTED_MODULE_9__.isAuthError)(_context2.t0)) {\n _context2.next = 15;\n break;\n }\n return _context2.abrupt(\"return\");\n case 15:\n throw _context2.t0;\n case 16:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, null, [[3, 10]]);\n }));\n return function handleTaskCreate(_x) {\n return _ref2.apply(this, arguments);\n };\n }();\n var handleTaskUpdate = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(updatedTask) {\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n if (updatedTask.id) {\n _context3.next = 3;\n break;\n }\n console.error(\"Cannot update task: Task ID is missing\");\n return _context3.abrupt(\"return\");\n case 3:\n _context3.prev = 3;\n _context3.next = 6;\n return (0,_utils_tasksService__WEBPACK_IMPORTED_MODULE_7__.updateTask)(updatedTask.id, updatedTask);\n case 6:\n setTasks(function (prevTasks) {\n return prevTasks.map(function (task) {\n return task.id === updatedTask.id ? updatedTask : task;\n });\n });\n _context3.next = 12;\n break;\n case 9:\n _context3.prev = 9;\n _context3.t0 = _context3[\"catch\"](3);\n console.error(\"Error updating task:\", _context3.t0);\n case 12:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3, null, [[3, 9]]);\n }));\n return function handleTaskUpdate(_x2) {\n return _ref3.apply(this, arguments);\n };\n }();\n var handleTaskDelete = /*#__PURE__*/function () {\n var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4(taskId) {\n return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n while (1) switch (_context4.prev = _context4.next) {\n case 0:\n if (taskId) {\n _context4.next = 3;\n break;\n }\n console.error(\"Cannot delete task: Task ID is missing\");\n return _context4.abrupt(\"return\");\n case 3:\n _context4.prev = 3;\n _context4.next = 6;\n return (0,_utils_tasksService__WEBPACK_IMPORTED_MODULE_7__.deleteTask)(taskId);\n case 6:\n setTasks(function (prevTasks) {\n return prevTasks.filter(function (task) {\n return task.id !== taskId;\n });\n });\n _context4.next = 12;\n break;\n case 9:\n _context4.prev = 9;\n _context4.t0 = _context4[\"catch\"](3);\n console.error(\"Error deleting task:\", _context4.t0);\n case 12:\n case \"end\":\n return _context4.stop();\n }\n }, _callee4, null, [[3, 9]]);\n }));\n return function handleTaskDelete(_x3) {\n return _ref4.apply(this, arguments);\n };\n }();\n var handleEditProject = function handleEditProject() {\n setIsModalOpen(true);\n };\n var handleSaveProject = /*#__PURE__*/function () {\n var _ref5 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee5(updatedProject) {\n var savedProject;\n return _regeneratorRuntime().wrap(function _callee5$(_context5) {\n while (1) switch (_context5.prev = _context5.next) {\n case 0:\n if (updatedProject.id) {\n _context5.next = 3;\n break;\n }\n console.error(\"Cannot save project: Project ID is missing\");\n return _context5.abrupt(\"return\");\n case 3:\n _context5.prev = 3;\n _context5.next = 6;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_6__.updateProject)(updatedProject.id, updatedProject);\n case 6:\n savedProject = _context5.sent;\n setProject(savedProject);\n setIsModalOpen(false);\n _context5.next = 14;\n break;\n case 11:\n _context5.prev = 11;\n _context5.t0 = _context5[\"catch\"](3);\n console.error(\"Error saving project:\", _context5.t0);\n case 14:\n case \"end\":\n return _context5.stop();\n }\n }, _callee5, null, [[3, 11]]);\n }));\n return function handleSaveProject(_x4) {\n return _ref5.apply(this, arguments);\n };\n }();\n var handleDeleteProject = /*#__PURE__*/function () {\n var _ref6 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee6() {\n return _regeneratorRuntime().wrap(function _callee6$(_context6) {\n while (1) switch (_context6.prev = _context6.next) {\n case 0:\n if (project !== null && project !== void 0 && project.id) {\n _context6.next = 3;\n break;\n }\n console.error(\"Cannot delete project: Project ID is missing\");\n return _context6.abrupt(\"return\");\n case 3:\n _context6.prev = 3;\n _context6.next = 6;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_6__.deleteProject)(project.id);\n case 6:\n navigate(\"/projects\");\n _context6.next = 12;\n break;\n case 9:\n _context6.prev = 9;\n _context6.t0 = _context6[\"catch\"](3);\n console.error(\"Error deleting project:\", _context6.t0);\n case 12:\n case \"end\":\n return _context6.stop();\n }\n }, _callee6, null, [[3, 9]]);\n }));\n return function handleDeleteProject() {\n return _ref6.apply(this, arguments);\n };\n }();\n if (loading) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-center h-screen bg-gray-100 dark:bg-gray-900\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-xl font-semibold text-gray-700 dark:text-gray-200\"\n }, \"Loading project details...\"));\n }\n if (error) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-center h-screen bg-gray-100 dark:bg-gray-900\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-red-500 text-lg\"\n }, error));\n }\n if (!project) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-center h-screen bg-gray-100 dark:bg-gray-900\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-red-500 text-lg\"\n }, \"Project not found.\"));\n }\n var activeTasks = (tasks === null || tasks === void 0 ? void 0 : tasks.filter(function (task) {\n return task.status !== 'done';\n })) || []; //TODO: Also add archived\n var completedTasks = tasks === null || tasks === void 0 ? void 0 : tasks.filter(function (task) {\n return task.status === 'done';\n });\n var toggleCompleted = function toggleCompleted() {\n setIsCompletedOpen(!isCompletedOpen);\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex justify-center px-4 lg:px-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-full max-w-5xl\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-between mb-8\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_11__[\"default\"], {\n className: \"h-6 w-6 text-gray-500 mr-3\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h2\", {\n className: \"text-2xl font-light text-gray-900 dark:text-gray-100 mr-2\"\n }, project.name), project.priority && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-4 h-4 rounded-full border-2 border-white dark:border-gray-800 \".concat(priorityStyles[project.priority] || priorityStyles[\"default\"]),\n title: \"Priority: \".concat(priorityLabel(project.priority)),\n \"aria-label\": \"Priority: \".concat(priorityLabel(project.priority))\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex space-x-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: handleEditProject,\n className: \"text-gray-500 hover:text-blue-700 dark:hover:text-blue-300 focus:outline-none\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_12__[\"default\"], {\n className: \"h-5 w-5\"\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n return setIsConfirmDialogOpen(true);\n },\n className: \"text-gray-500 hover:text-red-700 dark:hover:text-red-300 focus:outline-none\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_13__[\"default\"], {\n className: \"h-5 w-5\"\n })))), project.area && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center mb-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_14__[\"default\"], {\n className: \"h-5 w-5 text-gray-500 dark:text-gray-400 mr-2\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_15__.Link, {\n to: \"/projects/?area_id=\".concat(project.area.id),\n className: \"text-gray-600 dark:text-gray-400 hover:underline\"\n }, project.area.name.toUpperCase())), project.due_date_at && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center mb-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_16__[\"default\"], {\n className: \"h-5 w-5 text-gray-500 dark:text-gray-400 mr-2\"\n }), project.due_date_at), project.description && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"flex items-center text-gray-700 dark:text-gray-300 mb-6\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_17__[\"default\"], {\n className: \"h-5 w-5 text-gray-500 dark:text-gray-400 mr-2\"\n }), project.description), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Task_NewTask__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n onTaskCreate: handleTaskCreate\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mt-2\"\n }, activeTasks.length > 0 ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Task_TaskList__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n tasks: activeTasks,\n onTaskUpdate: handleTaskUpdate,\n onTaskDelete: handleTaskDelete,\n projects: project ? [project] : []\n }) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-gray-500 dark:text-gray-400\"\n }, \"No active tasks.\")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mt-6\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: toggleCompleted,\n className: \"flex items-center justify-between w-full px-4 py-2 bg-gray-200 dark:bg-gray-700 rounded-md focus:outline-none\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"text-sm uppercase font-medium\"\n }, \"Completed Tasks\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"svg\", {\n className: \"w-6 h-6 transform transition-transform duration-200 \".concat(isCompletedOpen ? \"rotate-180\" : \"rotate-0\"),\n fill: \"none\",\n stroke: \"currentColor\",\n viewBox: \"0 0 24 24\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"path\", {\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeWidth: 2,\n d: \"M19 9l-7 7-7-7\"\n }))), isCompletedOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mt-4\"\n }, completedTasks && completedTasks.length > 0 ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Task_TaskList__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n tasks: completedTasks,\n onTaskUpdate: handleTaskUpdate,\n onTaskDelete: handleTaskDelete,\n projects: project ? [project] : []\n }) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-gray-500 dark:text-gray-400\"\n }, \"No completed tasks.\"))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Project_ProjectModal__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n isOpen: isModalOpen,\n onClose: function onClose() {\n return setIsModalOpen(false);\n },\n onSave: handleSaveProject,\n project: project,\n areas: areas\n }), isConfirmDialogOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n title: \"Delete Project\",\n message: \"Are you sure you want to delete the project \\\"\".concat(project.name, \"\\\"?\"),\n onConfirm: handleDeleteProject,\n onCancel: function onCancel() {\n return setIsConfirmDialogOpen(false);\n }\n })));\n};\n_s(ProjectDetails, \"DXd0e9EF3zKJcJnY97T9u7uB/lI=\", false, function () {\n return [react_router_dom__WEBPACK_IMPORTED_MODULE_10__.useParams, react_router_dom__WEBPACK_IMPORTED_MODULE_10__.useNavigate, _store_useStore__WEBPACK_IMPORTED_MODULE_4__.useStore];\n});\n_c = ProjectDetails;\nvar priorityLabel = function priorityLabel(priority) {\n switch (priority) {\n case 'high':\n return 'High';\n case 'medium':\n return 'Medium';\n case 'low':\n return 'Low';\n default:\n return '';\n }\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ProjectDetails);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"ProjectDetails\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Project/ProjectDetails.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Project/ProjectItem.tsx": -/*!*****************************************************!*\ - !*** ./frontend/components/Project/ProjectItem.tsx ***! - \*****************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router-dom/dist/index.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/EllipsisVerticalIcon.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\n\n\n\n\nvar getProjectInitials = function getProjectInitials(name) {\n var words = name.trim().split(\" \").filter(function (word) {\n return word.length > 0;\n });\n if (words.length === 1) {\n return name.toUpperCase();\n }\n return words.map(function (word) {\n return word[0].toUpperCase();\n }).join(\"\");\n};\nvar ProjectItem = function ProjectItem(_ref) {\n _s();\n var project = _ref.project,\n viewMode = _ref.viewMode,\n color = _ref.color,\n getCompletionPercentage = _ref.getCompletionPercentage,\n activeDropdown = _ref.activeDropdown,\n setActiveDropdown = _ref.setActiveDropdown,\n handleEditProject = _ref.handleEditProject,\n setProjectToDelete = _ref.setProjectToDelete,\n setIsConfirmDialogOpen = _ref.setIsConfirmDialogOpen;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"\".concat(viewMode === \"cards\" ? \"bg-gray-50 dark:bg-gray-900 rounded-lg shadow-md relative flex flex-col\" : \"bg-gray-50 dark:bg-gray-900 rounded-lg shadow-md relative flex flex-row items-center p-4\"),\n style: {\n minHeight: viewMode === \"cards\" ? \"250px\" : \"auto\",\n maxHeight: viewMode === \"cards\" ? \"250px\" : \"auto\"\n }\n }, viewMode === \"cards\" && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"bg-gray-200 dark:bg-gray-700 flex items-center justify-center overflow-hidden rounded-t-lg\",\n style: {\n height: \"140px\"\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"text-2xl font-extrabold text-gray-500 dark:text-gray-400 opacity-20\",\n \"aria-label\": t(\"projectItem.projectInitials\")\n }, getProjectInitials(project.name)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"absolute top-2 left-2 w-3 h-3 rounded-full \".concat(color)\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex justify-between items-start \".concat(viewMode === \"cards\" ? \"p-4 flex-1\" : \"flex-1\")\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_2__.Link, {\n to: \"/project/\".concat(project.id),\n className: \"\".concat(viewMode === \"cards\" ? \"text-lg font-semibold text-gray-900 dark:text-gray-100 hover:underline line-clamp-2\" : \"text-md font-semibold text-gray-900 dark:text-gray-100 hover:underline\")\n }, project.name), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"relative\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n className: \"text-gray-500 hover:text-gray-700 dark:text-gray-300 dark:hover:text-gray-400 focus:outline-none\",\n onClick: function onClick() {\n var _project$id;\n return setActiveDropdown(activeDropdown === project.id ? null : (_project$id = project.id) !== null && _project$id !== void 0 ? _project$id : null);\n },\n \"aria-label\": t(\"projectItem.toggleDropdownMenu\")\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n className: \"h-5 w-5\"\n })), activeDropdown === project.id && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"absolute right-0 mt-2 w-28 bg-white dark:bg-gray-700 shadow-lg rounded-md z-10\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n return handleEditProject(project);\n },\n className: \"block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-600 w-full text-left\"\n }, t(\"projectItem.edit\")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n setProjectToDelete(project);\n setIsConfirmDialogOpen(true);\n setActiveDropdown(null);\n },\n className: \"block px-4 py-2 text-sm text-red-500 dark:text-red-300 hover:bg-gray-100 dark:hover:bg-gray-600 w-full text-left\"\n }, t(\"projectItem.delete\"))))), viewMode === \"cards\" && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"absolute bottom-4 left-0 right-0 px-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center space-x-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"bg-blue-500 h-2 rounded-full\",\n style: {\n width: \"\".concat(getCompletionPercentage(project === null || project === void 0 ? void 0 : project.id), \"%\")\n }\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"text-xs text-gray-500 dark:text-gray-400\"\n }, t(\"projectItem.completionPercentage\", {\n percentage: getCompletionPercentage(project === null || project === void 0 ? void 0 : project.id)\n })))));\n};\n_s(ProjectItem, \"zlIdU9EjM2llFt74AbE2KsUJXyM=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c = ProjectItem;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ProjectItem);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"ProjectItem\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Project/ProjectItem.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Project/ProjectModal.tsx": -/*!******************************************************!*\ - !*** ./frontend/components/Project/ProjectModal.tsx ***! - \******************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Shared/ConfirmDialog */ \"./frontend/components/Shared/ConfirmDialog.tsx\");\n/* harmony import */ var _Shared_ToastContext__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Shared/ToastContext */ \"./frontend/components/Shared/ToastContext.tsx\");\n/* harmony import */ var _Tag_TagInput__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Tag/TagInput */ \"./frontend/components/Tag/TagInput.tsx\");\n/* harmony import */ var _Shared_PriorityDropdown__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../Shared/PriorityDropdown */ \"./frontend/components/Shared/PriorityDropdown.tsx\");\n/* harmony import */ var _Shared_Switch__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../Shared/Switch */ \"./frontend/components/Shared/Switch.tsx\");\n/* harmony import */ var _store_useStore__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../store/useStore */ \"./frontend/store/useStore.ts\");\n/* harmony import */ var _utils_tagsService__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../utils/tagsService */ \"./frontend/utils/tagsService.ts\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\n\n\n\n\nvar ProjectModal = function ProjectModal(_ref) {\n _s();\n var _project$tags;\n var isOpen = _ref.isOpen,\n onClose = _ref.onClose,\n onSave = _ref.onSave,\n onDelete = _ref.onDelete,\n project = _ref.project,\n areas = _ref.areas;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(project || {\n name: \"\",\n description: \"\",\n area_id: null,\n active: true,\n tags: [],\n priority: \"low\",\n due_date_at: \"\"\n }),\n _useState2 = _slicedToArray(_useState, 2),\n formData = _useState2[0],\n setFormData = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)((project === null || project === void 0 || (_project$tags = project.tags) === null || _project$tags === void 0 ? void 0 : _project$tags.map(function (tag) {\n return tag.name;\n })) || []),\n _useState4 = _slicedToArray(_useState3, 2),\n tags = _useState4[0],\n setTags = _useState4[1];\n var _useStore = (0,_store_useStore__WEBPACK_IMPORTED_MODULE_6__.useStore)(),\n tagsStore = _useStore.tagsStore;\n var availableTags = tagsStore.tags;\n var modalRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState6 = _slicedToArray(_useState5, 2),\n isClosing = _useState6[0],\n setIsClosing = _useState6[1];\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState8 = _slicedToArray(_useState7, 2),\n showConfirmDialog = _useState8[0],\n setShowConfirmDialog = _useState8[1];\n var _useToast = (0,_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_2__.useToast)(),\n showSuccessToast = _useToast.showSuccessToast;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_8__.useTranslation)(),\n t = _useTranslation.t;\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n if (project) {\n var _project$tags2;\n setFormData(_objectSpread(_objectSpread({}, project), {}, {\n tags: project.tags || [],\n due_date_at: project.due_date_at || \"\"\n }));\n setTags(((_project$tags2 = project.tags) === null || _project$tags2 === void 0 ? void 0 : _project$tags2.map(function (tag) {\n return tag.name;\n })) || []);\n } else {\n setFormData({\n name: \"\",\n description: \"\",\n area_id: null,\n active: true,\n tags: [],\n priority: \"low\",\n due_date_at: \"\"\n });\n setTags([]);\n }\n }, [project]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n if (availableTags.length === 0) {\n (0,_utils_tagsService__WEBPACK_IMPORTED_MODULE_7__.fetchTags)();\n }\n }, [availableTags.length]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleClickOutside = function handleClickOutside(event) {\n if (modalRef.current && !modalRef.current.contains(event.target)) {\n handleClose();\n }\n };\n if (isOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n }\n return function () {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, [isOpen]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleKeyDown = function handleKeyDown(event) {\n if (event.key === \"Escape\") {\n handleClose();\n }\n };\n if (isOpen) {\n document.addEventListener(\"keydown\", handleKeyDown);\n }\n return function () {\n document.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [isOpen]);\n var handleChange = function handleChange(e) {\n var target = e.target;\n var name = target.name,\n type = target.type,\n value = target.value;\n if (type === \"checkbox\") {\n if (target instanceof HTMLInputElement) {\n var checked = target.checked;\n setFormData(function (prev) {\n return _objectSpread(_objectSpread({}, prev), {}, _defineProperty({}, name, checked));\n });\n }\n } else {\n setFormData(function (prev) {\n return _objectSpread(_objectSpread({}, prev), {}, _defineProperty({}, name, value));\n });\n }\n };\n var handleTagsChange = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(function (newTags) {\n setTags(newTags);\n setFormData(function (prev) {\n return _objectSpread(_objectSpread({}, prev), {}, {\n tags: newTags.map(function (name) {\n return {\n name: name\n };\n })\n });\n });\n }, []);\n var handleSubmit = function handleSubmit() {\n onSave(_objectSpread(_objectSpread({}, formData), {}, {\n tags: tags.map(function (name) {\n return {\n name: name\n };\n })\n }));\n showSuccessToast(project ? \"Project updated successfully!\" : \"Project created successfully!\");\n handleClose();\n };\n var handleDeleteClick = function handleDeleteClick() {\n setShowConfirmDialog(true);\n };\n var handleDeleteConfirm = function handleDeleteConfirm() {\n if (project && project.id && onDelete) {\n onDelete(project.id);\n showSuccessToast(\"Project deleted successfully!\");\n setShowConfirmDialog(false);\n handleClose();\n }\n };\n var handleClose = function handleClose() {\n setIsClosing(true);\n setTimeout(function () {\n onClose();\n setIsClosing(false);\n }, 300);\n };\n var handleToggleActive = function handleToggleActive() {\n setFormData(function (prev) {\n return _objectSpread(_objectSpread({}, prev), {}, {\n active: !prev.active\n });\n });\n };\n if (!isOpen) return null;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"fixed top-16 left-0 right-0 bottom-0 flex items-start sm:items-center justify-center bg-gray-900 bg-opacity-80 z-40 transition-opacity duration-300 \".concat(isClosing ? \"opacity-0\" : \"opacity-100\")\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n ref: modalRef,\n className: \"bg-white dark:bg-gray-800 sm:rounded-lg sm:shadow-2xl w-full sm:max-w-2xl overflow-hidden transform transition-transform duration-300 \".concat(isClosing ? \"scale-95\" : \"scale-100\", \" h-screen sm:h-auto flex flex-col\"),\n style: {\n maxHeight: \"calc(100vh - 4rem)\"\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"form\", {\n className: \"flex flex-col flex-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"fieldset\", {\n className: \"flex flex-col flex-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"p-4 space-y-3 flex-1 text-sm overflow-y-auto\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"py-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"text\",\n id: \"projectName\",\n name: \"name\",\n value: formData.name,\n onChange: handleChange,\n required: true,\n className: \"block w-full text-xl font-semibold dark:bg-gray-800 text-black dark:text-white border-b-2 border-gray-200 dark:border-gray-900 focus:outline-none shadow-sm py-2\",\n placeholder: t('project.name', 'Enter project name')\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"pb-3\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-xs font-medium text-gray-700 dark:text-gray-300 mb-2\"\n }, t('forms.description', 'Description')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"textarea\", {\n id: \"projectDescription\",\n name: \"description\",\n rows: 4,\n value: formData.description || \"\",\n onChange: handleChange,\n className: \"block w-full rounded-md shadow-sm p-3 text-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 transition duration-150 ease-in-out\",\n placeholder: t('forms.areaDescriptionPlaceholder', 'Enter project description (optional)')\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"pb-3\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-xs font-medium text-gray-700 dark:text-gray-300 mb-2\"\n }, t('forms.dueDate', 'Due Date')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"date\",\n name: \"due_date_at\",\n value: formData.due_date_at || \"\",\n onChange: handleChange,\n className: \"block w-full rounded-md shadow-sm px-3 py-2 text-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 transition duration-150 ease-in-out\"\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"pb-3\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-xs font-medium text-gray-700 dark:text-gray-300 mb-3\"\n }, t('forms.priority', 'Priority')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Shared_PriorityDropdown__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n value: formData.priority || \"medium\",\n onChange: function onChange(value) {\n return setFormData(_objectSpread(_objectSpread({}, formData), {}, {\n priority: value\n }));\n }\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"pb-3\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-xs font-medium text-gray-700 dark:text-gray-300 mb-2\"\n }, t('forms.tags', 'Tags')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-full\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Tag_TagInput__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n onTagsChange: handleTagsChange,\n initialTags: tags,\n availableTags: availableTags\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"pb-3\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-xs font-medium text-gray-700 dark:text-gray-300 mb-2\"\n }, t('common.area', 'Area'), \" (\", t('forms.optional', 'optional'), \")\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"select\", {\n id: \"projectArea\",\n name: \"area_id\",\n value: formData.area_id || \"\",\n onChange: handleChange,\n className: \"block w-full rounded-md shadow-sm px-3 py-2 text-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 transition duration-150 ease-in-out\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"\"\n }, t('common.none', 'No Area')), areas.map(function (area) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n key: area.id,\n value: area.id\n }, area.name);\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Shared_Switch__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n isChecked: formData.active,\n onToggle: handleToggleActive\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n htmlFor: \"active\",\n className: \"ml-2 block text-sm text-gray-700 dark:text-gray-300\"\n }, t('projects.active', 'Active')))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"p-3 flex-shrink-0 border-t border-gray-200 dark:border-gray-700 flex justify-end space-x-2\"\n }, project && onDelete && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: handleDeleteClick,\n className: \"px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-600 focus:outline-none transition duration-150 ease-in-out\"\n }, t('common.delete', 'Delete')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: handleClose,\n className: \"px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200 rounded-md hover:bg-gray-300 dark:hover:bg-gray-600 focus:outline-none transition duration-150 ease-in-out\"\n }, t('common.cancel', 'Cancel')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: handleSubmit,\n className: \"px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 focus:outline-none transition duration-150 ease-in-out\"\n }, project ? t('modals.updateProject', 'Update Project') : t('modals.createProject', 'Create Project'))))))), showConfirmDialog && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n title: \"Delete Project\",\n message: \"Are you sure you want to delete this project? This action cannot be undone.\",\n onConfirm: handleDeleteConfirm,\n onCancel: function onCancel() {\n return setShowConfirmDialog(false);\n }\n }));\n};\n_s(ProjectModal, \"2tHyU71UI68ZsRKowsM1xSi3kks=\", false, function () {\n return [_store_useStore__WEBPACK_IMPORTED_MODULE_6__.useStore, _Shared_ToastContext__WEBPACK_IMPORTED_MODULE_2__.useToast, react_i18next__WEBPACK_IMPORTED_MODULE_8__.useTranslation];\n});\n_c = ProjectModal;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ProjectModal);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"ProjectModal\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Project/ProjectModal.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Projects.tsx": -/*!******************************************!*\ - !*** ./frontend/components/Projects.tsx ***! - \******************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/FolderIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/Squares2X2Icon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/Bars3Icon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/MagnifyingGlassIcon.js\");\n/* harmony import */ var _Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Shared/ConfirmDialog */ \"./frontend/components/Shared/ConfirmDialog.tsx\");\n/* harmony import */ var _Project_ProjectModal__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Project/ProjectModal */ \"./frontend/components/Project/ProjectModal.tsx\");\n/* harmony import */ var _store_useStore__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../store/useStore */ \"./frontend/store/useStore.ts\");\n/* harmony import */ var _utils_projectsService__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/projectsService */ \"./frontend/utils/projectsService.ts\");\n/* harmony import */ var _utils_areasService__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils/areasService */ \"./frontend/utils/areasService.ts\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router-dom/dist/index.js\");\n/* harmony import */ var _Project_ProjectItem__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./Project/ProjectItem */ \"./frontend/components/Project/ProjectItem.tsx\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\n\n\n\n\n\nvar getPriorityStyles = function getPriorityStyles(priority) {\n switch (priority) {\n case \"low\":\n return {\n color: \"bg-green-500\"\n };\n case \"medium\":\n return {\n color: \"bg-yellow-500\"\n };\n case \"high\":\n return {\n color: \"bg-red-500\"\n };\n default:\n return {\n color: \"bg-gray-500\"\n };\n }\n};\nvar Projects = function Projects() {\n _s();\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_6__.useTranslation)(),\n t = _useTranslation.t;\n var _useStore = (0,_store_useStore__WEBPACK_IMPORTED_MODULE_3__.useStore)(function (state) {\n return state.areasStore;\n }),\n areas = _useStore.areas,\n setAreas = _useStore.setAreas,\n setAreasLoading = _useStore.setLoading,\n setAreasError = _useStore.setError;\n var _useStore2 = (0,_store_useStore__WEBPACK_IMPORTED_MODULE_3__.useStore)(function (state) {\n return state.projectsStore;\n }),\n projects = _useStore2.projects,\n setProjects = _useStore2.setProjects,\n setProjectsLoading = _useStore2.setLoading,\n setProjectsError = _useStore2.setError;\n var _useStore3 = (0,_store_useStore__WEBPACK_IMPORTED_MODULE_3__.useStore)(function (state) {\n return state.projectsStore;\n }),\n isLoading = _useStore3.isLoading,\n isError = _useStore3.isError;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)({}),\n _useState2 = _slicedToArray(_useState, 2),\n taskStatusCounts = _useState2[0],\n setTaskStatusCounts = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState4 = _slicedToArray(_useState3, 2),\n isProjectModalOpen = _useState4[0],\n setIsProjectModalOpen = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState6 = _slicedToArray(_useState5, 2),\n projectToEdit = _useState6[0],\n setProjectToEdit = _useState6[1];\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState8 = _slicedToArray(_useState7, 2),\n projectToDelete = _useState8[0],\n setProjectToDelete = _useState8[1];\n var _useState9 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState10 = _slicedToArray(_useState9, 2),\n isConfirmDialogOpen = _useState10[0],\n setIsConfirmDialogOpen = _useState10[1];\n var _useState11 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState12 = _slicedToArray(_useState11, 2),\n activeDropdown = _useState12[0],\n setActiveDropdown = _useState12[1];\n var _useState13 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(\"\"),\n _useState14 = _slicedToArray(_useState13, 2),\n searchQuery = _useState14[0],\n setSearchQuery = _useState14[1];\n var _useState15 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(\"cards\"),\n _useState16 = _slicedToArray(_useState15, 2),\n viewMode = _useState16[0],\n setViewMode = _useState16[1];\n var _useSearchParams = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_8__.useSearchParams)(),\n _useSearchParams2 = _slicedToArray(_useSearchParams, 2),\n searchParams = _useSearchParams2[0],\n setSearchParams = _useSearchParams2[1];\n var activeFilter = searchParams.get(\"active\") || \"all\";\n var areaFilter = searchParams.get(\"area_id\") || \"\";\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var loadAreas = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var areasData;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.prev = 0;\n _context.next = 3;\n return (0,_utils_areasService__WEBPACK_IMPORTED_MODULE_5__.fetchAreas)();\n case 3:\n areasData = _context.sent;\n setAreas(areasData);\n _context.next = 11;\n break;\n case 7:\n _context.prev = 7;\n _context.t0 = _context[\"catch\"](0);\n console.error(\"Failed to fetch areas:\", _context.t0);\n setAreasError(true);\n case 11:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[0, 7]]);\n }));\n return function loadAreas() {\n return _ref.apply(this, arguments);\n };\n }();\n loadAreas();\n }, []);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var loadProjects = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {\n var projectsData;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n _context2.prev = 0;\n _context2.next = 3;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_4__.fetchProjects)(activeFilter, areaFilter);\n case 3:\n projectsData = _context2.sent;\n setProjects(projectsData);\n _context2.next = 11;\n break;\n case 7:\n _context2.prev = 7;\n _context2.t0 = _context2[\"catch\"](0);\n console.error(\"Failed to fetch projects:\", _context2.t0);\n setProjectsError(true);\n case 11:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, null, [[0, 7]]);\n }));\n return function loadProjects() {\n return _ref2.apply(this, arguments);\n };\n }();\n loadProjects();\n }, [activeFilter, areaFilter]);\n var handleSaveProject = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(project) {\n var updatedProjects;\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n setProjectsLoading(true);\n _context3.prev = 1;\n if (!project.id) {\n _context3.next = 7;\n break;\n }\n _context3.next = 5;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_4__.updateProject)(project.id, project);\n case 5:\n _context3.next = 9;\n break;\n case 7:\n _context3.next = 9;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_4__.createProject)(project);\n case 9:\n _context3.next = 11;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_4__.fetchProjects)(activeFilter, areaFilter);\n case 11:\n updatedProjects = _context3.sent;\n setProjects(updatedProjects);\n _context3.next = 19;\n break;\n case 15:\n _context3.prev = 15;\n _context3.t0 = _context3[\"catch\"](1);\n console.error(\"Error saving project:\", _context3.t0);\n setProjectsError(true);\n case 19:\n _context3.prev = 19;\n setProjectsLoading(false);\n setIsProjectModalOpen(false);\n return _context3.finish(19);\n case 23:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3, null, [[1, 15, 19, 23]]);\n }));\n return function handleSaveProject(_x) {\n return _ref3.apply(this, arguments);\n };\n }();\n var handleEditProject = function handleEditProject(project) {\n setProjectToEdit(project);\n setIsProjectModalOpen(true);\n };\n var handleDeleteProject = /*#__PURE__*/function () {\n var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {\n var updatedProjects;\n return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n while (1) switch (_context4.prev = _context4.next) {\n case 0:\n if (projectToDelete) {\n _context4.next = 2;\n break;\n }\n return _context4.abrupt(\"return\");\n case 2:\n _context4.prev = 2;\n if (!(projectToDelete.id !== undefined)) {\n _context4.next = 13;\n break;\n }\n setProjectsLoading(true);\n _context4.next = 7;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_4__.deleteProject)(projectToDelete.id);\n case 7:\n _context4.next = 9;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_4__.fetchProjects)(activeFilter, areaFilter);\n case 9:\n updatedProjects = _context4.sent;\n setProjects(updatedProjects);\n _context4.next = 14;\n break;\n case 13:\n console.error(\"Cannot delete project: ID is undefined.\");\n case 14:\n _context4.next = 20;\n break;\n case 16:\n _context4.prev = 16;\n _context4.t0 = _context4[\"catch\"](2);\n console.error(\"Error deleting project:\", _context4.t0);\n setProjectsError(true);\n case 20:\n _context4.prev = 20;\n setProjectsLoading(false);\n setIsConfirmDialogOpen(false);\n setProjectToDelete(null);\n return _context4.finish(20);\n case 25:\n case \"end\":\n return _context4.stop();\n }\n }, _callee4, null, [[2, 16, 20, 25]]);\n }));\n return function handleDeleteProject() {\n return _ref4.apply(this, arguments);\n };\n }();\n var getCompletionPercentage = function getCompletionPercentage(projectId) {\n if (!projectId) return 0;\n var taskStatus = taskStatusCounts[projectId] || {\n not_started: 0,\n in_progress: 0,\n done: 0,\n archived: 0\n };\n var totalTasks = taskStatus.done + taskStatus.not_started + taskStatus.in_progress;\n if (totalTasks === 0) return 0;\n return Math.round(taskStatus.done / totalTasks * 100);\n };\n var handleActiveFilterChange = function handleActiveFilterChange(e) {\n var newActiveFilter = e.target.value;\n var params = new URLSearchParams(searchParams);\n if (newActiveFilter === \"all\") {\n params[\"delete\"](\"active\");\n } else {\n params.set(\"active\", newActiveFilter);\n }\n setSearchParams(params);\n };\n var handleAreaFilterChange = function handleAreaFilterChange(e) {\n var newAreaFilter = e.target.value;\n var params = new URLSearchParams(searchParams);\n if (newAreaFilter === \"\") {\n params[\"delete\"](\"area_id\");\n } else {\n params.set(\"area_id\", newAreaFilter);\n }\n setSearchParams(params);\n };\n var filteredProjects = projects.filter(function (project) {\n return project.name.toLowerCase().includes(searchQuery.toLowerCase());\n });\n var groupedProjects = filteredProjects.reduce(function (acc, project) {\n var areaName = project.area ? project.area.name : \"Uncategorized\";\n if (!acc[areaName]) acc[areaName] = [];\n acc[areaName].push(project);\n return acc;\n }, {});\n if (isLoading) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-center h-screen bg-gray-100 dark:bg-gray-900\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-xl font-semibold text-gray-700 dark:text-gray-200\"\n }, t('projects.loading')));\n }\n if (isError) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-center h-screen bg-gray-100 dark:bg-gray-900\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-red-500 text-lg\"\n }, t('projects.error')));\n }\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex justify-center px-4 lg:px-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-full max-w-6xl\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center mb-8\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_9__[\"default\"], {\n className: \"h-6 w-6 text-gray-500 mr-2\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h2\", {\n className: \"text-2xl font-light text-gray-900 dark:text-gray-100\"\n }, t('projects.title'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex flex-col md:flex-row md:items-center justify-between mb-6 space-y-4 md:space-y-0\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center space-x-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n return setViewMode(\"cards\");\n },\n className: \"p-2 rounded-md focus:outline-none \".concat(viewMode === \"cards\" ? \"bg-blue-500 text-white\" : \"bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300\"),\n \"aria-label\": t(\"projects.cardViewAriaLabel\")\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_10__[\"default\"], {\n className: \"h-5 w-5\"\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n return setViewMode(\"list\");\n },\n className: \"p-2 rounded-md focus:outline-none \".concat(viewMode === \"list\" ? \"bg-blue-500 text-white\" : \"bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300\"),\n \"aria-label\": t(\"projects.listViewAriaLabel\")\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_11__[\"default\"], {\n className: \"h-5 w-5\"\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex flex-col md:flex-row md:items-center md:space-x-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-full md:w-auto\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n htmlFor: \"activeFilter\",\n className: \"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\"\n }, t('common.status')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"select\", {\n id: \"activeFilter\",\n value: activeFilter,\n onChange: handleActiveFilterChange,\n className: \"block w-full p-2 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"true\"\n }, t('projects.filters.active')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"false\"\n }, t('projects.filters.inactive')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"all\"\n }, t('projects.filters.all')))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-full md:w-auto\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n htmlFor: \"areaFilter\",\n className: \"block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1\"\n }, t('common.area')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"select\", {\n id: \"areaFilter\",\n value: areaFilter,\n onChange: handleAreaFilterChange,\n className: \"block w-full p-2 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n value: \"\"\n }, t('projects.filters.allAreas')), areas.map(function (area) {\n var _area$id;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"option\", {\n key: area.id,\n value: (_area$id = area.id) === null || _area$id === void 0 ? void 0 : _area$id.toString()\n }, area.name);\n }))))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-md shadow-sm p-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_12__[\"default\"], {\n className: \"h-5 w-5 text-gray-500 dark:text-gray-400 mr-2\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"text\",\n placeholder: t('projects.searchPlaceholder'),\n value: searchQuery,\n onChange: function onChange(e) {\n return setSearchQuery(e.target.value);\n },\n className: \"w-full bg-transparent border-none focus:ring-0 focus:outline-none dark:text-white\"\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"\".concat(viewMode === \"cards\" ? \"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4\" : \"flex flex-col space-y-1\")\n }, Object.keys(groupedProjects).length === 0 ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-gray-700 dark:text-gray-300\"\n }, t('projects.noProjectsFound')) : Object.keys(groupedProjects).map(function (areaName) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), {\n key: areaName\n }, viewMode === \"cards\" && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h3\", {\n className: \"col-span-full text-md uppercase font-light text-gray-800 dark:text-gray-200 mb-2 mt-6\"\n }, areaName), groupedProjects[areaName].map(function (project) {\n var _getPriorityStyles = getPriorityStyles(project.priority || \"low\"),\n color = _getPriorityStyles.color;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Project_ProjectItem__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n key: project.id,\n project: project,\n viewMode: viewMode,\n color: color,\n getCompletionPercentage: getCompletionPercentage,\n activeDropdown: activeDropdown,\n setActiveDropdown: setActiveDropdown,\n handleEditProject: handleEditProject,\n setProjectToDelete: setProjectToDelete,\n setIsConfirmDialogOpen: setIsConfirmDialogOpen\n });\n }));\n }))), isProjectModalOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Project_ProjectModal__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n isOpen: isProjectModalOpen,\n onClose: function onClose() {\n setIsProjectModalOpen(false);\n setProjectToEdit(null);\n },\n onSave: handleSaveProject,\n project: projectToEdit || undefined,\n areas: areas\n }), isConfirmDialogOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n title: t('modals.deleteProject.title'),\n message: t('modals.deleteProject.message', {\n projectName: projectToDelete === null || projectToDelete === void 0 ? void 0 : projectToDelete.name\n }),\n onConfirm: handleDeleteProject,\n onCancel: function onCancel() {\n return setIsConfirmDialogOpen(false);\n }\n }));\n};\n_s(Projects, \"aW8dYoggpvaw23kfwWMeUwdAfyo=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_6__.useTranslation, _store_useStore__WEBPACK_IMPORTED_MODULE_3__.useStore, _store_useStore__WEBPACK_IMPORTED_MODULE_3__.useStore, _store_useStore__WEBPACK_IMPORTED_MODULE_3__.useStore, react_router_dom__WEBPACK_IMPORTED_MODULE_8__.useSearchParams];\n});\n_c = Projects;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Projects);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"Projects\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Projects.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Shared/ConfirmDialog.tsx": -/*!******************************************************!*\ - !*** ./frontend/components/Shared/ConfirmDialog.tsx ***! - \******************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\n\n\nvar ConfirmDialog = function ConfirmDialog(_ref) {\n _s();\n var title = _ref.title,\n message = _ref.message,\n onConfirm = _ref.onConfirm,\n onCancel = _ref.onCancel;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-50\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"bg-white dark:bg-gray-800 p-8 rounded-lg shadow-xl w-full max-w-lg mx-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h3\", {\n className: \"text-xl font-semibold mb-4 text-gray-900 dark:text-white\"\n }, title), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-gray-700 dark:text-gray-300 mb-8\"\n }, message), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex justify-end space-x-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: onCancel,\n className: \"px-4 py-2 bg-gray-300 text-gray-700 rounded hover:bg-gray-400 focus:outline-none\"\n }, t('common.cancel', 'Cancel')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: onConfirm,\n className: \"px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600 focus:outline-none\"\n }, t('common.delete', 'Delete')))));\n};\n_s(ConfirmDialog, \"zlIdU9EjM2llFt74AbE2KsUJXyM=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c = ConfirmDialog;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ConfirmDialog);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"ConfirmDialog\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Shared/ConfirmDialog.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Shared/LoadingScreen.tsx": -/*!******************************************************!*\ - !*** ./frontend/components/Shared/LoadingScreen.tsx ***! - \******************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\n\nvar LoadingScreen = function LoadingScreen() {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex h-screen w-screen items-center justify-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-lg\"\n }, \"Loading application... Please wait.\"));\n};\n_c = LoadingScreen;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LoadingScreen);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"LoadingScreen\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Shared/LoadingScreen.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Shared/NotFound.tsx": -/*!*************************************************!*\ - !*** ./frontend/components/Shared/NotFound.tsx ***! - \*************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\n\nvar NotFound = function NotFound() {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h1\", null, \"404 - Page Not Found\"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", null, \"The page you're looking for doesn't exist.\"));\n};\n_c = NotFound;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (NotFound);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"NotFound\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Shared/NotFound.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Shared/PriorityDropdown.tsx": -/*!*********************************************************!*\ - !*** ./frontend/components/Shared/PriorityDropdown.tsx ***! - \*********************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/ArrowDownIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/ArrowUpIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/FireIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/ChevronDownIcon.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\nvar PriorityDropdown = function PriorityDropdown(_ref) {\n _s();\n var value = _ref.value,\n onChange = _ref.onChange;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var priorities = [{\n value: 'low',\n label: t('priority.low', 'Low'),\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"w-5 h-5 text-gray-700 dark:text-gray-300\"\n })\n }, {\n value: 'medium',\n label: t('priority.medium', 'Medium'),\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n className: \"w-5 h-5 text-gray-700 dark:text-gray-300\"\n })\n }, {\n value: 'high',\n label: t('priority.high', 'High'),\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n className: \"w-5 h-5 text-gray-700 dark:text-gray-300\"\n })\n }];\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState2 = _slicedToArray(_useState, 2),\n isOpen = _useState2[0],\n setIsOpen = _useState2[1];\n var dropdownRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n var handleToggle = function handleToggle() {\n setIsOpen(!isOpen);\n };\n var handleClickOutside = function handleClickOutside(event) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n var handleSelect = function handleSelect(priority) {\n onChange(priority);\n setIsOpen(false);\n };\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n } else {\n document.removeEventListener('mousedown', handleClickOutside);\n }\n return function () {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [isOpen]);\n var selectedPriority = priorities.find(function (p) {\n return p.value === value;\n });\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n ref: dropdownRef,\n className: \"relative inline-block text-left w-full\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n className: \"inline-flex justify-between w-full px-3 py-2 bg-white dark:bg-gray-900 text-sm text-gray-900 dark:text-gray-100 border border-gray-300 dark:border-gray-900 rounded-md shadow-sm focus:outline-none\",\n onClick: handleToggle\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"flex items-center space-x-2\"\n }, selectedPriority ? selectedPriority.icon : '', /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", null, selectedPriority ? selectedPriority.label : t('forms.priority', 'Select Priority'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n className: \"w-5 h-5 text-gray-500 dark:text-gray-300\"\n })), isOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"absolute z-10 mt-2 w-full bg-white dark:bg-gray-700 shadow-lg rounded-md\"\n }, priorities.map(function (priority) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n key: priority.value,\n onClick: function onClick() {\n return handleSelect(priority.value);\n },\n className: \"flex items-center justify-between px-4 py-2 text-sm text-gray-900 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-600 w-full\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"flex items-center space-x-2\"\n }, priority.icon, \" \", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", null, priority.label)));\n })));\n};\n_s(PriorityDropdown, \"qFZaxaTpRrXhBQ1R1JrEH1Pyquk=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c = PriorityDropdown;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (PriorityDropdown);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"PriorityDropdown\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Shared/PriorityDropdown.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Shared/StatusDropdown.tsx": -/*!*******************************************************!*\ - !*** ./frontend/components/Shared/StatusDropdown.tsx ***! - \*******************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/MinusIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/ClockIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/CheckCircleIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/ArchiveBoxIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/ChevronDownIcon.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\nvar StatusDropdown = function StatusDropdown(_ref) {\n _s();\n var value = _ref.value,\n onChange = _ref.onChange;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var statuses = [{\n value: 'not_started',\n label: t('status.notStarted', 'Not Started'),\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"w-5 h-5 text-gray-700 dark:text-gray-300\"\n })\n }, {\n value: 'in_progress',\n label: t('status.inProgress', 'In Progress'),\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n className: \"w-5 h-5 text-gray-700 dark:text-gray-300\"\n })\n }, {\n value: 'done',\n label: t('status.done', 'Done'),\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n className: \"w-5 h-5 text-gray-700 dark:text-gray-300\"\n })\n }, {\n value: 'archived',\n label: t('status.archived', 'Archived'),\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n className: \"w-5 h-5 text-gray-700 dark:text-gray-300\"\n })\n }];\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState2 = _slicedToArray(_useState, 2),\n isOpen = _useState2[0],\n setIsOpen = _useState2[1];\n var dropdownRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n var handleToggle = function handleToggle() {\n setIsOpen(!isOpen);\n };\n var handleClickOutside = function handleClickOutside(event) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {\n setIsOpen(false);\n }\n };\n var handleSelect = function handleSelect(status) {\n onChange(status);\n setIsOpen(false);\n };\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n } else {\n document.removeEventListener('mousedown', handleClickOutside);\n }\n return function () {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [isOpen]);\n var selectedStatus = statuses.find(function (s) {\n return s.value === value;\n });\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n ref: dropdownRef,\n className: \"relative inline-block text-left w-full\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n className: \"inline-flex justify-between w-full px-3 py-2 bg-white dark:bg-gray-900 text-sm text-gray-900 dark:text-gray-100 border border-gray-300 dark:border-gray-900 rounded-md shadow-sm focus:outline-none\",\n onClick: handleToggle\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"flex items-center space-x-2\"\n }, selectedStatus ? selectedStatus.icon : '', /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", null, selectedStatus ? selectedStatus.label : 'Select Status')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n className: \"w-5 h-5 text-gray-500 dark:text-gray-300\"\n })), isOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"absolute z-10 mt-2 w-full bg-white dark:bg-gray-700 shadow-lg rounded-md\"\n }, statuses.map(function (status) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n key: status.value,\n onClick: function onClick() {\n return handleSelect(status.value);\n },\n className: \"flex items-center justify-between space-x-2 px-4 py-2 text-sm text-gray-900 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-600 w-full\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"flex items-center space-x-2\"\n }, status.icon, \" \", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", null, status.label)));\n })));\n};\n_s(StatusDropdown, \"qFZaxaTpRrXhBQ1R1JrEH1Pyquk=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c = StatusDropdown;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (StatusDropdown);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"StatusDropdown\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Shared/StatusDropdown.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Shared/Switch.tsx": -/*!***********************************************!*\ - !*** ./frontend/components/Shared/Switch.tsx ***! - \***********************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\n\nvar Switch = function Switch(_ref) {\n var isChecked = _ref.isChecked,\n onToggle = _ref.onToggle;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center space-x-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-12 h-6 flex items-center rounded-full p-1 cursor-pointer transition-all duration-300 \".concat(isChecked ? 'bg-blue-600' : 'bg-gray-300'),\n onClick: onToggle\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"bg-white w-4 h-4 rounded-full shadow-md transform transition-transform duration-300 \".concat(isChecked ? 'translate-x-6' : '')\n })));\n};\n_c = Switch;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Switch);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"Switch\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Shared/Switch.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Shared/ToastContext.tsx": -/*!*****************************************************!*\ - !*** ./frontend/components/Shared/ToastContext.tsx ***! - \*****************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ ToastProvider: () => (/* binding */ ToastProvider),\n/* harmony export */ useToast: () => (/* binding */ useToast)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature(),\n _s2 = __webpack_require__.$Refresh$.signature();\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\nvar ToastContext = /*#__PURE__*/(0,react__WEBPACK_IMPORTED_MODULE_0__.createContext)(undefined);\nvar ToastProvider = function ToastProvider(_ref) {\n _s();\n var children = _ref.children;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState2 = _slicedToArray(_useState, 2),\n toastMessage = _useState2[0],\n setToastMessage = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)('success'),\n _useState4 = _slicedToArray(_useState3, 2),\n toastType = _useState4[0],\n setToastType = _useState4[1];\n var showSuccessToast = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(function (message) {\n setToastMessage(message);\n setToastType('success');\n setTimeout(function () {\n return setToastMessage(null);\n }, 3000);\n }, []);\n var showErrorToast = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(function (message) {\n setToastMessage(message);\n setToastType('error');\n setTimeout(function () {\n return setToastMessage(null);\n }, 3000);\n }, []);\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(ToastContext.Provider, {\n value: {\n showSuccessToast: showSuccessToast,\n showErrorToast: showErrorToast\n }\n }, children, toastMessage && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(Toast, {\n message: toastMessage,\n type: toastType,\n onClose: function onClose() {\n return setToastMessage(null);\n }\n }));\n};\n_s(ToastProvider, \"LOKk7y55w/lPtCUhSKQrz3mvN9A=\");\n_c = ToastProvider;\nvar useToast = function useToast() {\n _s2();\n var context = (0,react__WEBPACK_IMPORTED_MODULE_0__.useContext)(ToastContext);\n if (context === undefined) {\n throw new Error('useToast must be used within a ToastProvider');\n }\n return context;\n};\n_s2(useToast, \"b9L3QQ+jgeyIrH0NfHrJ8nn7VMU=\");\nvar Toast = function Toast(_ref2) {\n var message = _ref2.message,\n type = _ref2.type,\n onClose = _ref2.onClose;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"fixed bottom-4 right-4 z-50 px-4 py-3 rounded-lg shadow-md text-white \".concat(type === 'success' ? 'bg-green-500' : 'bg-red-500')\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", null, message), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: onClose,\n className: \"ml-4\"\n }, \"\\xD7\"));\n};\n_c2 = Toast;\nvar _c, _c2;\n__webpack_require__.$Refresh$.register(_c, \"ToastProvider\");\n__webpack_require__.$Refresh$.register(_c2, \"Toast\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Shared/ToastContext.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Sidebar.tsx": -/*!*****************************************!*\ - !*** ./frontend/components/Sidebar.tsx ***! - \*****************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router/dist/index.js\");\n/* harmony import */ var _Sidebar_SidebarAreas__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Sidebar/SidebarAreas */ \"./frontend/components/Sidebar/SidebarAreas.tsx\");\n/* harmony import */ var _Sidebar_SidebarFooter__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Sidebar/SidebarFooter */ \"./frontend/components/Sidebar/SidebarFooter.tsx\");\n/* harmony import */ var _Sidebar_SidebarNav__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Sidebar/SidebarNav */ \"./frontend/components/Sidebar/SidebarNav.tsx\");\n/* harmony import */ var _Sidebar_SidebarNotes__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Sidebar/SidebarNotes */ \"./frontend/components/Sidebar/SidebarNotes.tsx\");\n/* harmony import */ var _Sidebar_SidebarProjects__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Sidebar/SidebarProjects */ \"./frontend/components/Sidebar/SidebarProjects.tsx\");\n/* harmony import */ var _Sidebar_SidebarTags__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./Sidebar/SidebarTags */ \"./frontend/components/Sidebar/SidebarTags.tsx\");\n/* harmony import */ var _Sidebar_CreateNewDropdownButton__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./Sidebar/CreateNewDropdownButton */ \"./frontend/components/Sidebar/CreateNewDropdownButton.tsx\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\n\n\n\n\nvar Sidebar = function Sidebar(_ref) {\n _s();\n var isSidebarOpen = _ref.isSidebarOpen,\n setIsSidebarOpen = _ref.setIsSidebarOpen,\n currentUser = _ref.currentUser,\n isDarkMode = _ref.isDarkMode,\n toggleDarkMode = _ref.toggleDarkMode,\n _openTaskModal = _ref.openTaskModal,\n openProjectModal = _ref.openProjectModal,\n openNoteModal = _ref.openNoteModal,\n openAreaModal = _ref.openAreaModal,\n openTagModal = _ref.openTagModal,\n notes = _ref.notes,\n areas = _ref.areas,\n tags = _ref.tags;\n var navigate = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_8__.useNavigate)();\n var location = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_8__.useLocation)();\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState2 = _slicedToArray(_useState, 2),\n isDropdownOpen = _useState2[0],\n setIsDropdownOpen = _useState2[1];\n var toggleDropdown = function toggleDropdown() {\n setIsDropdownOpen(!isDropdownOpen);\n };\n var handleNavClick = function handleNavClick(path, title, icon) {\n navigate(path, {\n state: {\n title: title\n }\n });\n if (window.innerWidth < 1024) {\n setIsSidebarOpen(false);\n }\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"fixed top-16 left-0 \".concat(isSidebarOpen ? 'w-full sm:w-72' : 'w-0', \" h-[calc(100vh-4rem)] bg-white dark:bg-gray-900 text-gray-900 dark:text-white transition-width duration-300 ease-in-out z-40\"),\n style: {\n visibility: isSidebarOpen ? 'visible' : 'hidden',\n overflow: 'hidden'\n }\n }, isSidebarOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex flex-col h-full overflow-y-auto\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"px-3 pb-3 pt-8\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Sidebar_CreateNewDropdownButton__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n openTaskModal: function openTaskModal(type) {\n return _openTaskModal(type || 'full');\n },\n openProjectModal: openProjectModal,\n openNoteModal: openNoteModal,\n openAreaModal: openAreaModal\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Sidebar_SidebarNav__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n handleNavClick: handleNavClick,\n location: location,\n isDarkMode: isDarkMode\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Sidebar_SidebarProjects__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n handleNavClick: handleNavClick,\n location: location,\n isDarkMode: isDarkMode,\n openProjectModal: openProjectModal\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Sidebar_SidebarNotes__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n handleNavClick: handleNavClick,\n openNoteModal: openNoteModal,\n notes: notes,\n location: location,\n isDarkMode: isDarkMode\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Sidebar_SidebarAreas__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n handleNavClick: handleNavClick,\n areas: areas,\n location: location,\n isDarkMode: isDarkMode,\n openAreaModal: openAreaModal\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Sidebar_SidebarTags__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n handleNavClick: handleNavClick,\n location: location,\n isDarkMode: isDarkMode,\n openTagModal: openTagModal,\n tags: tags\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Sidebar_SidebarFooter__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n currentUser: currentUser,\n isDarkMode: isDarkMode,\n toggleDarkMode: toggleDarkMode,\n isSidebarOpen: isSidebarOpen,\n setIsSidebarOpen: setIsSidebarOpen,\n isDropdownOpen: isDropdownOpen,\n toggleDropdown: toggleDropdown\n })));\n};\n_s(Sidebar, \"BuV5ye66dc5Hj9/s7y1G+tjc47E=\", false, function () {\n return [react_router_dom__WEBPACK_IMPORTED_MODULE_8__.useNavigate, react_router_dom__WEBPACK_IMPORTED_MODULE_8__.useLocation];\n});\n_c = Sidebar;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Sidebar);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"Sidebar\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Sidebar.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Sidebar/CreateNewDropdownButton.tsx": -/*!*****************************************************************!*\ - !*** ./frontend/components/Sidebar/CreateNewDropdownButton.tsx ***! - \*****************************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/ClipboardIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/FolderIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/BookOpenIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/Squares2X2Icon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/PlusCircleIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/ChevronDownIcon.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\nvar CreateNewDropdownButton = function CreateNewDropdownButton(_ref) {\n _s();\n var openTaskModal = _ref.openTaskModal,\n openProjectModal = _ref.openProjectModal,\n openNoteModal = _ref.openNoteModal,\n openAreaModal = _ref.openAreaModal;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState2 = _slicedToArray(_useState, 2),\n isDropdownOpen = _useState2[0],\n setIsDropdownOpen = _useState2[1];\n var toggleDropdown = function toggleDropdown() {\n setIsDropdownOpen(!isDropdownOpen);\n };\n var handleDropdownSelect = function handleDropdownSelect(type) {\n switch (type) {\n case 'Task':\n openTaskModal('full');\n break;\n case 'Project':\n openProjectModal();\n break;\n case 'Note':\n openNoteModal(null);\n break;\n case 'Area':\n openAreaModal(null);\n break;\n default:\n break;\n }\n setIsDropdownOpen(false);\n };\n var dropdownItems = [{\n label: 'Task',\n translationKey: 'dropdown.task',\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"h-5 w-5 mr-2\"\n })\n }, {\n label: 'Project',\n translationKey: 'dropdown.project',\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n className: \"h-5 w-5 mr-2\"\n })\n }, {\n label: 'Note',\n translationKey: 'dropdown.note',\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n className: \"h-5 w-5 mr-2\"\n })\n }, {\n label: 'Area',\n translationKey: 'dropdown.area',\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n className: \"h-5 w-5 mr-2\"\n })\n }];\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-8 px-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"relative\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n className: \"flex justify-between items-center w-full rounded-md border border-gray-300 dark:border-gray-700 shadow-sm px-4 py-2 bg-white dark:bg-gray-800 text-sm font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none\",\n onClick: toggleDropdown\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n className: \"w-5 h-5 mr-2 text-gray-500 dark:text-gray-400\",\n \"aria-hidden\": \"true\"\n }), t('dropdown.createNew', 'Create New')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n className: \"w-5 h-5 text-gray-500 dark:text-gray-400\",\n \"aria-hidden\": \"true\"\n })), isDropdownOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"absolute left-0 right-0 mt-2 w-full\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"rounded-md shadow-lg bg-white dark:bg-gray-800 ring-1 ring-black ring-opacity-5 z-10\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"ul\", {\n className: \"py-1\",\n role: \"menu\",\n \"aria-orientation\": \"vertical\",\n \"aria-labelledby\": \"options-menu\"\n }, dropdownItems.map(function (_ref2) {\n var label = _ref2.label,\n translationKey = _ref2.translationKey,\n icon = _ref2.icon;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"li\", {\n key: label,\n className: \"block px-4 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer flex items-center\",\n onClick: function onClick() {\n return handleDropdownSelect(label);\n },\n role: \"menuitem\"\n }, icon, t(translationKey, label));\n }))))));\n};\n_s(CreateNewDropdownButton, \"gRRtbMjmmvWyG7bcZ7YMLpNqbfg=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c = CreateNewDropdownButton;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CreateNewDropdownButton);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"CreateNewDropdownButton\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Sidebar/CreateNewDropdownButton.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Sidebar/SidebarAreas.tsx": -/*!******************************************************!*\ - !*** ./frontend/components/Sidebar/SidebarAreas.tsx ***! - \******************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/Squares2X2Icon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/PlusCircleIcon.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\n\n\n\nvar SidebarAreas = function SidebarAreas(_ref) {\n _s();\n var handleNavClick = _ref.handleNavClick,\n location = _ref.location,\n openAreaModal = _ref.openAreaModal;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var isActiveArea = function isActiveArea(path) {\n return location.pathname === path ? \"bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-white\" : \"text-gray-700 dark:text-gray-300\";\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"ul\", {\n className: \"flex flex-col space-y-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"li\", {\n className: \"flex justify-between items-center px-4 py-2 rounded-md uppercase text-xs tracking-wider cursor-pointer hover:text-black dark:hover:text-white \".concat(isActiveArea(\"/areas\")),\n onClick: function onClick() {\n return handleNavClick(\"/areas\", \"Areas\", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"h-5 w-5 mr-2\"\n }));\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"h-5 w-5 mr-2\"\n }), t('sidebar.areas')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick(e) {\n e.stopPropagation();\n openAreaModal(null);\n },\n className: \"text-gray-700 dark:text-gray-300 hover:text-black dark:hover:text-white focus:outline-none\",\n \"aria-label\": t('sidebar.addAreaAriaLabel'),\n title: t('sidebar.addAreaTitle')\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n className: \"h-5 w-5\"\n })))));\n};\n_s(SidebarAreas, \"zlIdU9EjM2llFt74AbE2KsUJXyM=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c = SidebarAreas;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SidebarAreas);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"SidebarAreas\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Sidebar/SidebarAreas.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Sidebar/SidebarFooter.tsx": -/*!*******************************************************!*\ - !*** ./frontend/components/Sidebar/SidebarFooter.tsx ***! - \*******************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/SunIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/MoonIcon.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\n\n\nvar SidebarFooter = function SidebarFooter(_ref) {\n var isDarkMode = _ref.isDarkMode,\n toggleDarkMode = _ref.toggleDarkMode,\n isSidebarOpen = _ref.isSidebarOpen,\n setIsSidebarOpen = _ref.setIsSidebarOpen;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mt-auto p-3\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"border-t border-gray-200 dark:border-gray-700 pt-3\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-center\"\n }, isSidebarOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: toggleDarkMode,\n className: \"focus:outline-none text-gray-700 dark:text-gray-300\",\n \"aria-label\": \"Toggle Dark Mode\"\n }, isDarkMode ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n className: \"h-6 w-6 text-yellow-500\"\n }) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"h-6 w-6 text-gray-500\"\n })))));\n};\n_c = SidebarFooter;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SidebarFooter);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"SidebarFooter\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Sidebar/SidebarFooter.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Sidebar/SidebarNav.tsx": -/*!****************************************************!*\ - !*** ./frontend/components/Sidebar/SidebarNav.tsx ***! - \****************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/InboxIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/CalendarDaysIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/CalendarIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/ArrowRightCircleIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/CheckCircleIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/ListBulletIcon.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\n\n\n\nvar SidebarNav = function SidebarNav(_ref) {\n _s();\n var handleNavClick = _ref.handleNavClick,\n location = _ref.location;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var navLinks = [{\n path: '/inbox',\n title: t('sidebar.inbox', 'Inbox'),\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"h-5 w-5\"\n })\n }, {\n path: '/today',\n title: t('sidebar.today', 'Today'),\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n className: \"h-5 w-5\"\n }),\n query: 'type=today'\n }, {\n path: '/tasks?type=upcoming',\n title: t('sidebar.upcoming', 'Upcoming'),\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n className: \"h-5 w-5\"\n }),\n query: 'type=upcoming'\n }, {\n path: '/tasks?type=next',\n title: t('sidebar.nextActions', 'Next Actions'),\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n className: \"h-5 w-5\"\n }),\n query: 'type=next'\n },\n // { path: '/tasks?type=someday', title: t('sidebar.someday', 'Someday'), icon: , query: 'type=someday' },\n // { path: '/tasks?type=waiting', title: t('sidebar.waitingFor', 'Waiting for'), icon: , query: 'type=waiting' },\n {\n path: '/tasks?status=done',\n title: t('sidebar.completed', 'Completed'),\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n className: \"h-5 w-5\"\n }),\n query: 'status=done'\n }, {\n path: '/tasks',\n title: t('sidebar.allTasks', 'All Tasks'),\n icon: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n className: \"h-5 w-5\"\n })\n }];\n var isActive = function isActive(path, query) {\n // Handle special case for paths without query parameters\n if (path === '/inbox' || path === '/today') {\n var _isPathMatch = location.pathname === path;\n return _isPathMatch ? 'bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-white' : 'text-gray-700 dark:text-gray-300';\n }\n\n // Regular case for /tasks with query params\n var isPathMatch = location.pathname === '/tasks';\n var isQueryMatch = query ? location.search.includes(query) : location.search === '';\n return isPathMatch && isQueryMatch ? 'bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-white' : 'text-gray-700 dark:text-gray-300';\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"ul\", {\n className: \"flex flex-col space-y-1\"\n }, navLinks.map(function (link) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), {\n key: link.path\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"li\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n return handleNavClick(link.path, link.title, link.icon);\n },\n className: \"w-full text-left px-4 py-1 flex items-center rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-all duration-200 \".concat(isActive(link.path, link.query))\n }, link.icon, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"ml-2\"\n }, link.title))), link.path === '/inbox' && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"li\", {\n className: \"py-1\"\n }));\n }));\n};\n_s(SidebarNav, \"zlIdU9EjM2llFt74AbE2KsUJXyM=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c = SidebarNav;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SidebarNav);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"SidebarNav\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Sidebar/SidebarNav.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Sidebar/SidebarNotes.tsx": -/*!******************************************************!*\ - !*** ./frontend/components/Sidebar/SidebarNotes.tsx ***! - \******************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/BookOpenIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/PlusCircleIcon.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\n\n\n\nvar SidebarNotes = function SidebarNotes(_ref) {\n _s();\n var handleNavClick = _ref.handleNavClick,\n location = _ref.location,\n openNoteModal = _ref.openNoteModal;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var isActiveNote = function isActiveNote(path) {\n return location.pathname === path ? 'bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-white' : 'text-gray-700 dark:text-gray-300';\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"ul\", {\n className: \"flex flex-col space-y-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"li\", {\n className: \"flex justify-between items-center rounded-md px-4 py-2 uppercase text-xs tracking-wider cursor-pointer hover:text-black dark:hover:text-white \".concat(isActiveNote('/notes')),\n onClick: function onClick() {\n return handleNavClick('/notes', 'Notes', /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"h-5 w-5 mr-2\"\n }));\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"h-5 w-5 mr-2\"\n }), t('sidebar.notes')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick(e) {\n e.stopPropagation();\n openNoteModal(null);\n },\n className: \"text-gray-700 dark:text-gray-300 hover:text-black dark:hover:text-white focus:outline-none\",\n \"aria-label\": \"Add Note\",\n title: \"Add Note\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n className: \"h-5 w-5\"\n })))));\n};\n_s(SidebarNotes, \"zlIdU9EjM2llFt74AbE2KsUJXyM=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c = SidebarNotes;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SidebarNotes);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"SidebarNotes\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Sidebar/SidebarNotes.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Sidebar/SidebarProjects.tsx": -/*!*********************************************************!*\ - !*** ./frontend/components/Sidebar/SidebarProjects.tsx ***! - \*********************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/FolderIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/PlusCircleIcon.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\n\n\n\nvar SidebarProjects = function SidebarProjects(_ref) {\n _s();\n var handleNavClick = _ref.handleNavClick,\n location = _ref.location,\n openProjectModal = _ref.openProjectModal;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var isActiveProject = function isActiveProject(path) {\n return location.pathname === path ? 'bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-white' : 'text-gray-700 dark:text-gray-300';\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"ul\", {\n className: \"flex flex-col space-y-1 mt-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"li\", {\n className: \"flex justify-between items-center px-4 py-2 uppercase rounded-md text-xs tracking-wider cursor-pointer hover:text-black dark:hover:text-white \".concat(isActiveProject('/projects')),\n onClick: function onClick() {\n return handleNavClick('/projects?active=true', 'Projects', /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"h-5 w-5 mr-2\"\n }));\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"h-5 w-5 mr-2\"\n }), t('sidebar.projects')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick(e) {\n e.stopPropagation();\n openProjectModal();\n },\n className: \"text-gray-700 dark:text-gray-300 hover:text-black dark:hover:text-white focus:outline-none\",\n \"aria-label\": \"Add Project\",\n title: \"Add Project\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n className: \"h-5 w-5\"\n })))));\n};\n_s(SidebarProjects, \"zlIdU9EjM2llFt74AbE2KsUJXyM=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c = SidebarProjects;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SidebarProjects);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"SidebarProjects\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Sidebar/SidebarProjects.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Sidebar/SidebarTags.tsx": -/*!*****************************************************!*\ - !*** ./frontend/components/Sidebar/SidebarTags.tsx ***! - \*****************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/TagIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/PlusCircleIcon.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\n\n\n\nvar SidebarTags = function SidebarTags(_ref) {\n _s();\n var handleNavClick = _ref.handleNavClick,\n location = _ref.location,\n openTagModal = _ref.openTagModal;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var isActiveTag = function isActiveTag(path) {\n return location.pathname === path ? 'bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-white' : 'text-gray-700 dark:text-gray-300';\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"ul\", {\n className: \"flex flex-col space-y-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"li\", {\n className: \"flex justify-between items-center rounded-md px-4 py-2 uppercase text-xs tracking-wider cursor-pointer hover:text-black dark:hover:text-white \".concat(isActiveTag('/tags')),\n onClick: function onClick() {\n return handleNavClick('/tags', 'Tags', /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"h-5 w-5 mr-2\"\n }));\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"h-5 w-5 mr-2\"\n }), t('sidebar.tags')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick(e) {\n e.stopPropagation();\n openTagModal(null);\n },\n className: \"text-gray-700 dark:text-gray-300 hover:text-black dark:hover:text-white focus:outline-none\",\n \"aria-label\": t('sidebar.addTagAriaLabel'),\n title: t('sidebar.addTagTitle')\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n className: \"h-5 w-5\"\n })))));\n};\n_s(SidebarTags, \"zlIdU9EjM2llFt74AbE2KsUJXyM=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c = SidebarTags;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SidebarTags);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"SidebarTags\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Sidebar/SidebarTags.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Tag/TagDetails.tsx": -/*!************************************************!*\ - !*** ./frontend/components/Tag/TagDetails.tsx ***! - \************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router/dist/index.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\nvar TagDetails = function TagDetails() {\n _s();\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var _useParams = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_2__.useParams)(),\n id = _useParams.id;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState2 = _slicedToArray(_useState, 2),\n tag = _useState2[0],\n setTag = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(true),\n _useState4 = _slicedToArray(_useState3, 2),\n loading = _useState4[0],\n setLoading = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState6 = _slicedToArray(_useState5, 2),\n error = _useState6[0],\n setError = _useState6[1];\n var navigate = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_2__.useNavigate)();\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var fetchTag = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var response, data;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.prev = 0;\n _context.next = 3;\n return fetch(\"/api/tag/\".concat(id));\n case 3:\n response = _context.sent;\n _context.next = 6;\n return response.json();\n case 6:\n data = _context.sent;\n if (response.ok) {\n setTag(data);\n } else {\n setError(data.error || 'Failed to fetch tag.');\n }\n _context.next = 13;\n break;\n case 10:\n _context.prev = 10;\n _context.t0 = _context[\"catch\"](0);\n setError(t('tags.error'));\n case 13:\n _context.prev = 13;\n setLoading(false);\n return _context.finish(13);\n case 16:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[0, 10, 13, 16]]);\n }));\n return function fetchTag() {\n return _ref.apply(this, arguments);\n };\n }();\n fetchTag();\n }, [id]);\n var handleViewTasks = function handleViewTasks() {\n if (tag) {\n navigate(\"/tasks?tag=\".concat(encodeURIComponent(tag.name)));\n }\n };\n if (loading) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-gray-700 dark:text-gray-300\"\n }, t('tags.loading'));\n }\n if (error) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-red-500\"\n }, error);\n }\n if (!tag) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-gray-700 dark:text-gray-300\"\n }, t('tags.notFound'));\n }\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"p-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h2\", {\n className: \"text-2xl font-semibold mb-4 text-gray-900 dark:text-white\"\n }, t('tags.details')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-gray-700 dark:text-gray-300\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"strong\", null, t('tags.name'), \":\"), \" \", tag.name), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-gray-700 dark:text-gray-300\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"strong\", null, t('tags.status'), \":\"), \" \", tag.active ? t('tags.active') : t('tags.inactive')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: handleViewTasks,\n className: \"mt-4 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600\"\n }, t('tags.viewTasksWithTag')));\n};\n_s(TagDetails, \"4kQAe5nObdk53DhKAFihpur76xE=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation, react_router_dom__WEBPACK_IMPORTED_MODULE_2__.useParams, react_router_dom__WEBPACK_IMPORTED_MODULE_2__.useNavigate];\n});\n_c = TagDetails;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TagDetails);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"TagDetails\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Tag/TagDetails.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Tag/TagInput.tsx": -/*!**********************************************!*\ - !*** ./frontend/components/Tag/TagInput.tsx ***! - \**********************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\nvar TagInput = function TagInput(_ref) {\n _s();\n var initialTags = _ref.initialTags,\n onTagsChange = _ref.onTagsChange,\n availableTags = _ref.availableTags;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(''),\n _useState2 = _slicedToArray(_useState, 2),\n inputValue = _useState2[0],\n setInputValue = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(initialTags || []),\n _useState4 = _slicedToArray(_useState3, 2),\n tags = _useState4[0],\n setTags = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)([]),\n _useState6 = _slicedToArray(_useState5, 2),\n filteredTags = _useState6[0],\n setFilteredTags = _useState6[1];\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState8 = _slicedToArray(_useState7, 2),\n isDropdownOpen = _useState8[0],\n setIsDropdownOpen = _useState8[1];\n var _useState9 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(-1),\n _useState10 = _slicedToArray(_useState9, 2),\n highlightedIndex = _useState10[0],\n setHighlightedIndex = _useState10[1];\n var inputRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n var containerRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n var dropdownRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n\n // Update internal tags state when initialTags prop changes\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n // Set the tags state with the initial tags\n if (initialTags && initialTags.length > 0) {\n // Simply set our internal state to match the initialTags\n setTags(initialTags);\n }\n }, [initialTags]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n onTagsChange(tags);\n }, [tags, onTagsChange]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handler = setTimeout(function () {\n if (inputValue.trim() === '') {\n setFilteredTags([]);\n setIsDropdownOpen(false);\n return;\n }\n var filtered = availableTags.filter(function (tag) {\n return tag.name.toLowerCase().includes(inputValue.toLowerCase()) && !tags.includes(tag.name);\n });\n setFilteredTags(filtered);\n setIsDropdownOpen(filtered.length > 0);\n setHighlightedIndex(-1);\n }, 300);\n return function () {\n clearTimeout(handler);\n };\n }, [inputValue, availableTags, tags]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleClickOutside = function handleClickOutside(event) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target) && containerRef.current && !containerRef.current.contains(event.target)) {\n setIsDropdownOpen(false);\n }\n };\n document.addEventListener('mousedown', handleClickOutside);\n return function () {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, []);\n var handleInputChange = function handleInputChange(event) {\n setInputValue(event.target.value);\n };\n var handleKeyDown = function handleKeyDown(event) {\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n setHighlightedIndex(function (prev) {\n return prev < filteredTags.length - 1 ? prev + 1 : prev;\n });\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n setHighlightedIndex(function (prev) {\n return prev > 0 ? prev - 1 : prev;\n });\n } else if (event.key === 'Enter') {\n event.preventDefault();\n if (highlightedIndex >= 0 && highlightedIndex < filteredTags.length) {\n selectTag(filteredTags[highlightedIndex].name);\n } else if (inputValue.trim()) {\n addNewTag(inputValue.trim());\n }\n } else if (event.key === 'Escape') {\n setIsDropdownOpen(false);\n } else if (event.key === ',') {\n if (inputValue.trim()) {\n event.preventDefault();\n addNewTag(inputValue.trim());\n }\n }\n };\n var addNewTag = function addNewTag(tag) {\n if (tags.length >= 10) {\n return;\n }\n if (!tags.includes(tag)) {\n var updatedTags = [].concat(_toConsumableArray(tags), [tag]);\n setTags(updatedTags);\n onTagsChange(updatedTags);\n }\n setInputValue('');\n setIsDropdownOpen(false);\n };\n var selectTag = function selectTag(tag) {\n if (!tags.includes(tag)) {\n var updatedTags = [].concat(_toConsumableArray(tags), [tag]);\n setTags(updatedTags);\n onTagsChange(updatedTags);\n }\n setInputValue('');\n setIsDropdownOpen(false);\n };\n var removeTag = function removeTag(index) {\n var updatedTags = tags.filter(function (_, i) {\n return i !== index;\n });\n setTags(updatedTags);\n onTagsChange(updatedTags);\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"space-y-2 relative\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n ref: containerRef,\n className: \"flex flex-wrap items-center border border-gray-300 dark:border-gray-900 bg-white dark:bg-gray-900 rounded-md p-2 min-h-[40px]\"\n }, tags.length > 0 ? tags.map(function (tag, index) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n key: index,\n className: \"flex items-center bg-gray-200 text-gray-700 text-xs font-medium mr-2 px-2.5 py-0.5 rounded\"\n }, tag, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: function onClick() {\n return removeTag(index);\n },\n className: \"ml-1 text-gray-600 hover:text-gray-800 focus:outline-none\",\n \"aria-label\": \"Remove tag \".concat(tag)\n }, \"\\xD7\"));\n }) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"text-gray-400 text-xs\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"text\",\n ref: inputRef,\n value: inputValue,\n onChange: handleInputChange,\n onKeyDown: handleKeyDown,\n placeholder: t('tags.typeToAdd'),\n className: \"flex-grow bg-transparent border-none outline-none text-sm text-gray-900 dark:text-gray-100\",\n onFocus: function onFocus() {\n if (filteredTags.length > 0) setIsDropdownOpen(true);\n },\n style: {\n minWidth: '150px'\n },\n \"aria-haspopup\": \"listbox\",\n \"aria-expanded\": isDropdownOpen,\n \"aria-controls\": \"tag-suggestions\"\n })), isDropdownOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n ref: dropdownRef,\n className: \"absolute z-10 mt-1 w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-md shadow-lg max-h-60 overflow-auto\",\n role: \"listbox\",\n id: \"tag-suggestions\"\n }, filteredTags.map(function (tag, index) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n key: tag.id,\n type: \"button\",\n onClick: function onClick() {\n return selectTag(tag.name);\n },\n className: \"w-full text-left px-4 py-2 text-sm hover:bg-gray-200 dark:hover:bg-gray-700 \".concat(highlightedIndex === index ? 'bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-gray-100' : 'text-gray-700 dark:text-gray-300'),\n onMouseEnter: function onMouseEnter() {\n return setHighlightedIndex(index);\n },\n onMouseLeave: function onMouseLeave() {\n return setHighlightedIndex(-1);\n },\n role: \"option\",\n \"aria-selected\": highlightedIndex === index\n }, highlightedIndex === index ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, inputValue.length > 0 && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"font-semibold\"\n }, tag.name.substring(0, inputValue.length)), tag.name.substring(inputValue.length)) : tag.name);\n }), filteredTags.length === 0 && inputValue.trim() !== '' && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: function onClick() {\n return addNewTag(inputValue.trim());\n },\n className: \"w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700\",\n role: \"option\"\n }, \"+ Create \\\"\", inputValue.trim(), \"\\\"\")));\n};\n_s(TagInput, \"6tqm3RRoLSNhluKVOj/UJlL/Iwg=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c = TagInput;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TagInput);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"TagInput\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Tag/TagInput.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Tag/TagModal.tsx": -/*!**********************************************!*\ - !*** ./frontend/components/Tag/TagModal.tsx ***! - \**********************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _Shared_ToastContext__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Shared/ToastContext */ \"./frontend/components/Shared/ToastContext.tsx\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\nvar TagModal = function TagModal(_ref) {\n _s();\n var isOpen = _ref.isOpen,\n onClose = _ref.onClose,\n onSave = _ref.onSave,\n tag = _ref.tag;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(tag || {\n name: ''\n }),\n _useState2 = _slicedToArray(_useState, 2),\n formData = _useState2[0],\n setFormData = _useState2[1];\n var modalRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState4 = _slicedToArray(_useState3, 2),\n isClosing = _useState4[0],\n setIsClosing = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState6 = _slicedToArray(_useState5, 2),\n isSubmitting = _useState6[0],\n setIsSubmitting = _useState6[1];\n var _useToast = (0,_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_1__.useToast)(),\n showSuccessToast = _useToast.showSuccessToast,\n showErrorToast = _useToast.showErrorToast;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_2__.useTranslation)(),\n t = _useTranslation.t;\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n if (tag) {\n setFormData(tag);\n } else {\n setFormData({\n name: ''\n });\n }\n }, [tag]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleClickOutside = function handleClickOutside(event) {\n if (modalRef.current && !modalRef.current.contains(event.target)) {\n handleClose();\n }\n };\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n return function () {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [isOpen]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleKeyDown = function handleKeyDown(event) {\n if (event.key === 'Escape') {\n handleClose();\n }\n };\n if (isOpen) {\n document.addEventListener('keydown', handleKeyDown);\n }\n return function () {\n document.removeEventListener('keydown', handleKeyDown);\n };\n }, [isOpen]);\n var handleChange = function handleChange(e) {\n var _e$target = e.target,\n name = _e$target.name,\n value = _e$target.value;\n setFormData(function (prev) {\n return _objectSpread(_objectSpread({}, prev), {}, _defineProperty({}, name, value));\n });\n };\n var handleSubmit = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n if (formData.name.trim()) {\n _context.next = 3;\n break;\n }\n showErrorToast(t('errors.tagNameRequired', 'Tag name is required.'));\n return _context.abrupt(\"return\");\n case 3:\n setIsSubmitting(true);\n try {\n if (tag) {\n showSuccessToast(t('success.tagUpdated', 'Tag updated successfully!'));\n } else {\n showSuccessToast(t('success.tagCreated', 'Tag created successfully!'));\n }\n onSave(formData);\n handleClose();\n } catch (err) {\n showErrorToast(t('errors.failedToSaveTag', 'Failed to save tag.'));\n } finally {\n setIsSubmitting(false);\n }\n case 5:\n case \"end\":\n return _context.stop();\n }\n }, _callee);\n }));\n return function handleSubmit() {\n return _ref2.apply(this, arguments);\n };\n }();\n var handleClose = function handleClose() {\n setIsClosing(true);\n setTimeout(function () {\n onClose();\n setIsClosing(false);\n }, 300);\n };\n if (!isOpen) return null;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"fixed top-16 left-0 right-0 bottom-0 flex items-start sm:items-center justify-center bg-gray-900 bg-opacity-80 z-40 transition-opacity duration-300 \".concat(isClosing ? 'opacity-0' : 'opacity-100')\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n ref: modalRef,\n className: \"bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-800 sm:rounded-lg sm:shadow-2xl w-full sm:max-w-md overflow-hidden transform transition-transform duration-300 \".concat(isClosing ? 'scale-95' : 'scale-100', \" h-screen sm:h-auto flex flex-col\"),\n style: {\n maxHeight: 'calc(100vh - 4rem)'\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"form\", {\n className: \"flex flex-col flex-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"fieldset\", {\n className: \"flex flex-col flex-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"p-4 space-y-3 flex-1 text-sm overflow-y-auto\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"py-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"text\",\n id: \"tagName\",\n name: \"name\",\n value: formData.name,\n onChange: handleChange,\n required: true,\n className: \"block w-full text-xl font-semibold dark:bg-gray-800 text-black dark:text-white border-b-2 border-gray-200 dark:border-gray-900 focus:outline-none shadow-sm py-2\",\n placeholder: t('forms.tagNamePlaceholder', 'Enter tag name')\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"p-3 flex-shrink-0 border-t border-gray-200 dark:border-gray-700 flex justify-end space-x-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: handleClose,\n className: \"px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200 rounded-md hover:bg-gray-300 dark:hover:bg-gray-600 focus:outline-none transition duration-150 ease-in-out\"\n }, t('common.cancel', 'Cancel')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: handleSubmit,\n disabled: isSubmitting,\n className: \"px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 focus:outline-none transition duration-150 ease-in-out \".concat(isSubmitting ? 'opacity-50 cursor-not-allowed' : '')\n }, isSubmitting ? t('modals.submitting', 'Submitting...') : tag ? t('modals.updateTag', 'Update Tag') : t('modals.createTag', 'Create Tag'))))))));\n};\n_s(TagModal, \"DEEDWSBiCUuJwhCRMel9CbEhkTQ=\", false, function () {\n return [_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_1__.useToast, react_i18next__WEBPACK_IMPORTED_MODULE_2__.useTranslation];\n});\n_c = TagModal;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TagModal);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"TagModal\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Tag/TagModal.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Tags.tsx": -/*!**************************************!*\ - !*** ./frontend/components/Tags.tsx ***! - \**************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router-dom/dist/index.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/TagIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/MagnifyingGlassIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/PencilSquareIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/TrashIcon.js\");\n/* harmony import */ var _Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Shared/ConfirmDialog */ \"./frontend/components/Shared/ConfirmDialog.tsx\");\n/* harmony import */ var _Tag_TagModal__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Tag/TagModal */ \"./frontend/components/Tag/TagModal.tsx\");\n/* harmony import */ var _utils_tagsService__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/tagsService */ \"./frontend/utils/tagsService.ts\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\n\nvar Tags = function Tags() {\n _s();\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)([]),\n _useState2 = _slicedToArray(_useState, 2),\n tags = _useState2[0],\n setTags = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState4 = _slicedToArray(_useState3, 2),\n isTagModalOpen = _useState4[0],\n setIsTagModalOpen = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState6 = _slicedToArray(_useState5, 2),\n selectedTag = _useState6[0],\n setSelectedTag = _useState6[1];\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState8 = _slicedToArray(_useState7, 2),\n isConfirmDialogOpen = _useState8[0],\n setIsConfirmDialogOpen = _useState8[1];\n var _useState9 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null),\n _useState10 = _slicedToArray(_useState9, 2),\n tagToDelete = _useState10[0],\n setTagToDelete = _useState10[1];\n var _useState11 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(''),\n _useState12 = _slicedToArray(_useState11, 2),\n searchQuery = _useState12[0],\n setSearchQuery = _useState12[1];\n var _useState13 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(true),\n _useState14 = _slicedToArray(_useState13, 2),\n isLoading = _useState14[0],\n setIsLoading = _useState14[1];\n var _useState15 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState16 = _slicedToArray(_useState15, 2),\n isError = _useState16[0],\n setIsError = _useState16[1];\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var loadTags = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var fetchedTags;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n setIsLoading(true);\n _context.prev = 1;\n _context.next = 4;\n return (0,_utils_tagsService__WEBPACK_IMPORTED_MODULE_3__.fetchTags)();\n case 4:\n fetchedTags = _context.sent;\n setTags(fetchedTags);\n _context.next = 12;\n break;\n case 8:\n _context.prev = 8;\n _context.t0 = _context[\"catch\"](1);\n console.error('Failed to fetch tags:', _context.t0);\n setIsError(true);\n case 12:\n _context.prev = 12;\n setIsLoading(false);\n return _context.finish(12);\n case 15:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[1, 8, 12, 15]]);\n }));\n return function loadTags() {\n return _ref.apply(this, arguments);\n };\n }();\n loadTags();\n }, []);\n var handleDeleteTag = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n if (tagToDelete) {\n _context2.next = 2;\n break;\n }\n return _context2.abrupt(\"return\");\n case 2:\n _context2.prev = 2;\n _context2.next = 5;\n return (0,_utils_tagsService__WEBPACK_IMPORTED_MODULE_3__.deleteTag)(tagToDelete.id);\n case 5:\n setTags(function (prev) {\n return prev.filter(function (tag) {\n return tag.id !== tagToDelete.id;\n });\n });\n setIsConfirmDialogOpen(false);\n setTagToDelete(null);\n _context2.next = 13;\n break;\n case 10:\n _context2.prev = 10;\n _context2.t0 = _context2[\"catch\"](2);\n console.error('Failed to delete tag:', _context2.t0);\n case 13:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, null, [[2, 10]]);\n }));\n return function handleDeleteTag() {\n return _ref2.apply(this, arguments);\n };\n }();\n var handleEditTag = function handleEditTag(tag) {\n setSelectedTag(tag);\n setIsTagModalOpen(true);\n };\n var handleSaveTag = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(tagData) {\n var updatedTags, newTag;\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n _context3.prev = 0;\n if (!tagData.id) {\n _context3.next = 7;\n break;\n }\n _context3.next = 4;\n return (0,_utils_tagsService__WEBPACK_IMPORTED_MODULE_3__.updateTag)(tagData.id, tagData);\n case 4:\n updatedTags = tags.map(function (tag) {\n return tag.id === tagData.id ? tagData : tag;\n });\n _context3.next = 11;\n break;\n case 7:\n _context3.next = 9;\n return (0,_utils_tagsService__WEBPACK_IMPORTED_MODULE_3__.createTag)(tagData);\n case 9:\n newTag = _context3.sent;\n updatedTags = [].concat(_toConsumableArray(tags), [newTag]);\n case 11:\n setTags(updatedTags);\n setIsTagModalOpen(false);\n setSelectedTag(null);\n _context3.next = 19;\n break;\n case 16:\n _context3.prev = 16;\n _context3.t0 = _context3[\"catch\"](0);\n console.error('Failed to save tag:', _context3.t0);\n case 19:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3, null, [[0, 16]]);\n }));\n return function handleSaveTag(_x) {\n return _ref3.apply(this, arguments);\n };\n }();\n var openConfirmDialog = function openConfirmDialog(tag) {\n setTagToDelete(tag);\n setIsConfirmDialogOpen(true);\n };\n var closeConfirmDialog = function closeConfirmDialog() {\n setIsConfirmDialogOpen(false);\n setTagToDelete(null);\n };\n var filteredTags = tags.filter(function (tag) {\n return tag.name.toLowerCase().includes(searchQuery.toLowerCase());\n });\n if (isLoading) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-center h-screen bg-gray-100 dark:bg-gray-900\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-xl font-semibold text-gray-700 dark:text-gray-200\"\n }, \"Loading tags...\"));\n }\n if (isError) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-red-500 p-4\"\n }, \"Error loading tags.\");\n }\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex justify-center px-4 lg:px-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-full max-w-5xl\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-between mb-8\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n className: \"h-6 w-6 mr-2 text-gray-900 dark:text-white\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h2\", {\n className: \"text-2xl font-light text-gray-900 dark:text-white\"\n }, \"Tags\"))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-md shadow-sm p-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n className: \"h-5 w-5 text-gray-500 dark:text-gray-400 mr-2\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"text\",\n placeholder: \"Search tags...\",\n value: searchQuery,\n onChange: function onChange(e) {\n return setSearchQuery(e.target.value);\n },\n className: \"w-full bg-transparent border-none focus:ring-0 focus:outline-none dark:text-white\"\n }))), filteredTags.length === 0 ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-gray-700 dark:text-gray-300\"\n }, \"No tags found.\") : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"ul\", {\n className: \"grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4\"\n }, filteredTags.map(function (tag) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"li\", {\n key: tag.id,\n className: \"bg-white dark:bg-gray-900 shadow rounded-lg p-4 flex justify-between items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex-grow overflow-hidden pr-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_6__.Link, {\n to: \"/tag/\".concat(tag.id),\n className: \"text-md font-semibold text-gray-900 dark:text-gray-100 hover:underline block\"\n }, tag.name)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex space-x-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n return handleEditTag(tag);\n },\n className: \"text-gray-500 hover:text-blue-700 dark:hover:text-blue-300 focus:outline-none\",\n \"aria-label\": \"Edit \".concat(tag.name),\n title: \"Edit \".concat(tag.name)\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n className: \"h-5 w-5\"\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n onClick: function onClick() {\n return openConfirmDialog(tag);\n },\n className: \"text-gray-500 hover:text-red-700 dark:hover:text-red-300 focus:outline-none\",\n \"aria-label\": \"Delete \".concat(tag.name),\n title: \"Delete \".concat(tag.name)\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_8__[\"default\"], {\n className: \"h-5 w-5\"\n }))));\n })), isTagModalOpen && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Tag_TagModal__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n isOpen: isTagModalOpen,\n onClose: function onClose() {\n return setIsTagModalOpen(false);\n },\n onSave: handleSaveTag,\n tag: selectedTag\n }), isConfirmDialogOpen && tagToDelete && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n title: \"Delete Tag\",\n message: \"Are you sure you want to delete the tag \\\"\".concat(tagToDelete.name, \"\\\"?\"),\n onConfirm: handleDeleteTag,\n onCancel: closeConfirmDialog\n })));\n};\n_s(Tags, \"buxoz4V4fR63Ntxhlvk23iPmaQ8=\");\n_c = Tags;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Tags);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"Tags\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Tags.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Task/NewTask.tsx": -/*!**********************************************!*\ - !*** ./frontend/components/Task/NewTask.tsx ***! - \**********************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _components_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../components/Shared/ToastContext */ \"./frontend/components/Shared/ToastContext.tsx\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/PlusCircleIcon.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\nvar NewTask = function NewTask(_ref) {\n _s();\n var onTaskCreate = _ref.onTaskCreate;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(''),\n _useState2 = _slicedToArray(_useState, 2),\n taskName = _useState2[0],\n setTaskName = _useState2[1];\n var _useToast = (0,_components_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_1__.useToast)(),\n showSuccessToast = _useToast.showSuccessToast,\n showErrorToast = _useToast.showErrorToast;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_2__.useTranslation)(),\n t = _useTranslation.t;\n var handleInputChange = function handleInputChange(event) {\n setTaskName(event.target.value);\n };\n var handleKeyDown = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(event) {\n var taskText;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n if (!(event.key === 'Enter' && taskName.trim())) {\n _context.next = 14;\n break;\n }\n taskText = taskName.trim();\n setTaskName('');\n _context.prev = 3;\n _context.next = 6;\n return onTaskCreate(taskText);\n case 6:\n showSuccessToast(t('success.taskCreated', 'Task created successfully!'));\n _context.next = 14;\n break;\n case 9:\n _context.prev = 9;\n _context.t0 = _context[\"catch\"](3);\n console.error('Error creating task:', _context.t0);\n setTaskName(taskText);\n showErrorToast(t('errors.taskCreate', 'Failed to create task.'));\n case 14:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[3, 9]]);\n }));\n return function handleKeyDown(_x) {\n return _ref2.apply(this, arguments);\n };\n }();\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-between py-3 px-4 mb-2 border-b border-gray-200 dark:border-gray-800 rounded-lg shadow-sm bg-white dark:bg-gray-900\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"text-xl text-gray-500 dark:text-gray-400 mr-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n className: \"h-6 w-6\"\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"text\",\n value: taskName,\n onChange: handleInputChange,\n onKeyDown: handleKeyDown,\n className: \"font-medium text-sm text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-600 bg-transparent dark:bg-transparent focus:outline-none focus:ring-0 w-full appearance-none\",\n placeholder: t('tasks.addNewTask', 'Προσθήκη Νέας Εργασίας')\n }));\n};\n_s(NewTask, \"KBYdgqzOlHVePvYN4KVfaPQiRAI=\", false, function () {\n return [_components_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_1__.useToast, react_i18next__WEBPACK_IMPORTED_MODULE_2__.useTranslation];\n});\n_c = NewTask;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (NewTask);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"NewTask\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Task/NewTask.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Task/SimplifiedTaskModal.tsx": -/*!**********************************************************!*\ - !*** ./frontend/components/Task/SimplifiedTaskModal.tsx ***! - \**********************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _Shared_ToastContext__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Shared/ToastContext */ \"./frontend/components/Shared/ToastContext.tsx\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* harmony import */ var _utils_inboxService__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../utils/inboxService */ \"./frontend/utils/inboxService.ts\");\n/* harmony import */ var _utils_authUtils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../utils/authUtils */ \"./frontend/utils/authUtils.ts\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\nvar SimplifiedTaskModal = function SimplifiedTaskModal(_ref) {\n _s();\n var isOpen = _ref.isOpen,\n onClose = _ref.onClose,\n onSave = _ref.onSave,\n _ref$initialText = _ref.initialText,\n initialText = _ref$initialText === void 0 ? \"\" : _ref$initialText,\n _ref$editMode = _ref.editMode,\n editMode = _ref$editMode === void 0 ? false : _ref$editMode,\n onEdit = _ref.onEdit;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_2__.useTranslation)(),\n t = _useTranslation.t;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(initialText),\n _useState2 = _slicedToArray(_useState, 2),\n inputText = _useState2[0],\n setInputText = _useState2[1];\n var modalRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState4 = _slicedToArray(_useState3, 2),\n isClosing = _useState4[0],\n setIsClosing = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState6 = _slicedToArray(_useState5, 2),\n isSaving = _useState6[0],\n setIsSaving = _useState6[1];\n var _useToast = (0,_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_1__.useToast)(),\n showSuccessToast = _useToast.showSuccessToast,\n showErrorToast = _useToast.showErrorToast;\n var nameInputRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)('inbox'),\n _useState8 = _slicedToArray(_useState7, 2),\n saveMode = _useState8[0],\n setSaveMode = _useState8[1];\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n if (isOpen && nameInputRef.current) {\n nameInputRef.current.focus();\n }\n }, [isOpen]);\n var handleChange = function handleChange(e) {\n setInputText(e.target.value);\n };\n var handleSubmit = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var newTask;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n if (!(!inputText.trim() || isSaving)) {\n _context.next = 2;\n break;\n }\n return _context.abrupt(\"return\");\n case 2:\n setIsSaving(true);\n _context.prev = 3;\n if (!(editMode && onEdit)) {\n _context.next = 10;\n break;\n }\n _context.next = 7;\n return onEdit(inputText.trim());\n case 7:\n setIsClosing(true);\n setTimeout(function () {\n onClose();\n setIsClosing(false);\n }, 300);\n return _context.abrupt(\"return\");\n case 10:\n if (!(saveMode === 'task')) {\n _context.next = 27;\n break;\n }\n newTask = {\n name: inputText.trim(),\n status: \"not_started\"\n };\n _context.prev = 12;\n _context.next = 15;\n return onSave(newTask);\n case 15:\n showSuccessToast(t('task.createSuccess'));\n setInputText('');\n handleClose();\n _context.next = 25;\n break;\n case 20:\n _context.prev = 20;\n _context.t0 = _context[\"catch\"](12);\n if (!(0,_utils_authUtils__WEBPACK_IMPORTED_MODULE_4__.isAuthError)(_context.t0)) {\n _context.next = 24;\n break;\n }\n return _context.abrupt(\"return\");\n case 24:\n throw _context.t0;\n case 25:\n _context.next = 39;\n break;\n case 27:\n _context.prev = 27;\n _context.next = 30;\n return (0,_utils_inboxService__WEBPACK_IMPORTED_MODULE_3__.createInboxItemWithStore)(inputText.trim());\n case 30:\n showSuccessToast(t('inbox.itemAdded'));\n handleClose();\n _context.next = 39;\n break;\n case 34:\n _context.prev = 34;\n _context.t1 = _context[\"catch\"](27);\n console.error('Failed to create inbox item:', _context.t1);\n showErrorToast(t('inbox.addError'));\n setIsSaving(false);\n case 39:\n _context.next = 45;\n break;\n case 41:\n _context.prev = 41;\n _context.t2 = _context[\"catch\"](3);\n console.error('Failed to save:', _context.t2);\n if (editMode) {\n showErrorToast(t('inbox.updateError'));\n } else {\n showErrorToast(saveMode === 'task' ? t('task.createError') : t('inbox.addError'));\n }\n case 45:\n _context.prev = 45;\n setIsSaving(false);\n return _context.finish(45);\n case 48:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[3, 41, 45, 48], [12, 20], [27, 34]]);\n })), [inputText, isSaving, editMode, onEdit, saveMode, onSave, showSuccessToast, showErrorToast, t, onClose]);\n var handleClose = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(function () {\n setIsClosing(true);\n setTimeout(function () {\n onClose();\n if (!editMode) {\n setInputText(\"\");\n setSaveMode('inbox');\n }\n setIsClosing(false);\n }, 300);\n }, [onClose, editMode]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleClickOutside = function handleClickOutside(event) {\n if (modalRef.current && !modalRef.current.contains(event.target)) {\n handleClose();\n }\n };\n if (isOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n }\n return function () {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, [isOpen]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleKeyDown = function handleKeyDown(event) {\n if (event.key === \"Escape\") {\n handleClose();\n }\n };\n if (isOpen) {\n document.addEventListener(\"keydown\", handleKeyDown);\n }\n return function () {\n document.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [isOpen, handleClose]); // Only depend on isOpen and handleClose\n\n if (!isOpen) return null;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"fixed top-16 left-0 right-0 bottom-0 flex items-start sm:items-center justify-center bg-gray-900 bg-opacity-80 z-40 transition-opacity duration-300 \".concat(isClosing ? \"opacity-0\" : \"opacity-100\")\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n ref: modalRef,\n className: \"bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-800 sm:rounded-lg sm:shadow-2xl w-full sm:max-w-2xl md:max-w-3xl overflow-hidden transform transition-transform duration-300 \".concat(isClosing ? \"scale-95\" : \"scale-100\", \" flex flex-col\")\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"p-6 px-8 flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n ref: nameInputRef,\n type: \"text\",\n name: \"text\",\n value: inputText,\n onChange: handleChange,\n required: true,\n className: \"flex-1 text-xl font-semibold dark:bg-gray-800 text-black dark:text-white border-b-2 border-gray-200 dark:border-gray-900 focus:outline-none shadow-sm py-2\",\n placeholder: t('inbox.captureThought'),\n onKeyDown: function onKeyDown(e) {\n if (e.key === 'Enter' && !e.shiftKey && !isSaving) {\n e.preventDefault();\n handleSubmit();\n }\n }\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: handleSubmit,\n disabled: !inputText.trim() || isSaving,\n className: \"ml-4 inline-flex justify-center px-4 py-2 text-sm font-medium text-white rounded-md shadow-sm focus:outline-none \".concat(inputText.trim() && !isSaving ? \"bg-blue-600 hover:bg-blue-700\" : \"bg-blue-400 cursor-not-allowed\")\n }, isSaving ? t('common.saving') : t('common.save')))));\n};\n_s(SimplifiedTaskModal, \"DWNnd+E4d5xZbiFE6qnSRK0VsZQ=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_2__.useTranslation, _Shared_ToastContext__WEBPACK_IMPORTED_MODULE_1__.useToast];\n});\n_c = SimplifiedTaskModal;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SimplifiedTaskModal);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"SimplifiedTaskModal\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Task/SimplifiedTaskModal.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Task/TaskActions.tsx": -/*!**************************************************!*\ - !*** ./frontend/components/Task/TaskActions.tsx ***! - \**************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\n\n\nvar TaskActions = function TaskActions(_ref) {\n _s();\n var taskId = _ref.taskId,\n onDelete = _ref.onDelete,\n onSave = _ref.onSave,\n onCancel = _ref.onCancel;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"p-3 border-t dark:border-gray-700 flex-shrink-0 flex justify-end space-x-2\"\n }, taskId && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: onDelete,\n className: \"px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 dark:bg-red-500 dark:hover:bg-red-600\"\n }, t('common.delete', 'Delete')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: onCancel,\n className: \"px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200 rounded hover:bg-gray-300 dark:hover:bg-gray-600\"\n }, t('common.cancel', 'Cancel')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: onSave,\n className: \"px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600\"\n }, t('common.save', 'Save')));\n};\n_s(TaskActions, \"zlIdU9EjM2llFt74AbE2KsUJXyM=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c = TaskActions;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TaskActions);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"TaskActions\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Task/TaskActions.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Task/TaskDueDate.tsx": -/*!**************************************************!*\ - !*** ./frontend/components/Task/TaskDueDate.tsx ***! - \**************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\n\n\nvar TaskDueDate = function TaskDueDate(_ref) {\n _s();\n var dueDate = _ref.dueDate,\n className = _ref.className;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var getDueDateClass = function getDueDateClass() {\n var today = new Date().toISOString().split('T')[0];\n var tomorrow = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString().split('T')[0];\n if (dueDate === today) return 'border-blue-700 dark:text-white';\n if (dueDate === tomorrow) return 'border-blue-700 dark:text-white';\n if (dueDate < today) return 'border-red-700 dark:text-white';\n return 'border-gray-300 dark:text-white';\n };\n var formatDueDate = function formatDueDate() {\n var today = new Date().toISOString().split('T')[0];\n var tomorrow = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString().split('T')[0];\n var yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString().split('T')[0];\n if (dueDate === today) return t('dateIndicators.today', 'TODAY');\n if (dueDate === tomorrow) return t('dateIndicators.tomorrow', 'TOMORROW');\n if (dueDate === yesterday) return t('dateIndicators.yesterday', 'YESTERDAY');\n return new Date(dueDate).toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric'\n });\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center text-xs py-1 px-2 rounded-md border \".concat(getDueDateClass(), \" \").concat(className)\n }, formatDueDate());\n};\n_s(TaskDueDate, \"zlIdU9EjM2llFt74AbE2KsUJXyM=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c = TaskDueDate;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TaskDueDate);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"TaskDueDate\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Task/TaskDueDate.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Task/TaskHeader.tsx": -/*!*************************************************!*\ - !*** ./frontend/components/Task/TaskHeader.tsx ***! - \*************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _TaskPriorityIcon__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./TaskPriorityIcon */ \"./frontend/components/Task/TaskPriorityIcon.tsx\");\n/* harmony import */ var _TaskTags__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./TaskTags */ \"./frontend/components/Task/TaskTags.tsx\");\n/* harmony import */ var _TaskStatusBadge__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./TaskStatusBadge */ \"./frontend/components/Task/TaskStatusBadge.tsx\");\n/* harmony import */ var _TaskDueDate__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./TaskDueDate */ \"./frontend/components/Task/TaskDueDate.tsx\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\n\n\n\n\n\nvar TaskHeader = function TaskHeader(_ref) {\n var task = _ref.task,\n project = _ref.project,\n onTaskClick = _ref.onTaskClick;\n var capitalizeFirstLetter = function capitalizeFirstLetter(string) {\n if (!string) {\n return \"\";\n }\n return string.charAt(0).toUpperCase() + string.slice(1);\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"py-2 px-4 cursor-pointer\",\n onClick: onTaskClick\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"hidden md:flex flex-col md:flex-row md:items-center md:justify-between\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center space-x-4 mb-2 md:mb-0\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_TaskPriorityIcon__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n priority: task.priority,\n status: task.status\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex flex-col\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"text-md text-gray-900 dark:text-gray-100\"\n }, task.name), project && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-xs text-gray-500 dark:text-gray-400\"\n }, project.name))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center flex-wrap justify-start md:justify-end space-x-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_TaskTags__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n tags: task.tags || []\n }), task.due_date && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_TaskDueDate__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n dueDate: task.due_date\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_TaskStatusBadge__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n status: task.status\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"block md:hidden\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-start font-light text-md text-gray-900 dark:text-gray-100\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_TaskPriorityIcon__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n priority: task.priority,\n status: task.status\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"ml-2 flex flex-col\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", null, task.name), project && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"text-xs text-gray-500 dark:text-gray-400 mt-1\"\n }, project.name)))));\n};\n_c = TaskHeader;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TaskHeader);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"TaskHeader\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Task/TaskHeader.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Task/TaskItem.tsx": -/*!***********************************************!*\ - !*** ./frontend/components/Task/TaskItem.tsx ***! - \***********************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _TaskHeader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./TaskHeader */ \"./frontend/components/Task/TaskHeader.tsx\");\n/* harmony import */ var _TaskModal__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./TaskModal */ \"./frontend/components/Task/TaskModal.tsx\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\nvar TaskItem = function TaskItem(_ref) {\n _s();\n var task = _ref.task,\n onTaskUpdate = _ref.onTaskUpdate,\n onTaskDelete = _ref.onTaskDelete,\n projects = _ref.projects;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState2 = _slicedToArray(_useState, 2),\n isModalOpen = _useState2[0],\n setIsModalOpen = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(projects),\n _useState4 = _slicedToArray(_useState3, 2),\n projectList = _useState4[0],\n setProjectList = _useState4[1];\n var handleTaskClick = function handleTaskClick() {\n setIsModalOpen(true);\n };\n var handleSave = function handleSave(updatedTask) {\n onTaskUpdate(updatedTask);\n setIsModalOpen(false);\n };\n var handleDelete = function handleDelete() {\n if (task.id) {\n onTaskDelete(task.id);\n }\n };\n var handleCreateProject = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(name) {\n var response, newProject;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.prev = 0;\n _context.next = 3;\n return fetch('/api/project', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({\n name: name,\n active: true\n })\n });\n case 3:\n response = _context.sent;\n if (response.ok) {\n _context.next = 6;\n break;\n }\n throw new Error('Failed to create project');\n case 6:\n _context.next = 8;\n return response.json();\n case 8:\n newProject = _context.sent;\n setProjectList(function (prevProjects) {\n return [].concat(_toConsumableArray(prevProjects), [newProject]);\n });\n return _context.abrupt(\"return\", newProject);\n case 13:\n _context.prev = 13;\n _context.t0 = _context[\"catch\"](0);\n console.error('Error creating project:', _context.t0);\n throw _context.t0;\n case 17:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[0, 13]]);\n }));\n return function handleCreateProject(_x) {\n return _ref2.apply(this, arguments);\n };\n }();\n var project = projectList.find(function (p) {\n return p.id === task.project_id;\n });\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"rounded-lg shadow-sm bg-white dark:bg-gray-900 mt-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_TaskHeader__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n task: task,\n project: project,\n onTaskClick: handleTaskClick\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_TaskModal__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n isOpen: isModalOpen,\n onClose: function onClose() {\n return setIsModalOpen(false);\n },\n task: task,\n onSave: handleSave,\n onDelete: handleDelete,\n projects: projectList,\n onCreateProject: handleCreateProject\n }));\n};\n_s(TaskItem, \"nPVTAiszvgH11lFcf0xprYGPwt4=\");\n_c = TaskItem;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TaskItem);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"TaskItem\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Task/TaskItem.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Task/TaskList.tsx": -/*!***********************************************!*\ - !*** ./frontend/components/Task/TaskList.tsx ***! - \***********************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _TaskItem__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./TaskItem */ \"./frontend/components/Task/TaskItem.tsx\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\n\n\nvar TaskList = function TaskList(_ref) {\n var tasks = _ref.tasks,\n onTaskUpdate = _ref.onTaskUpdate,\n onTaskDelete = _ref.onTaskDelete,\n projects = _ref.projects;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", null, tasks.length > 0 ? tasks.map(function (task) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_TaskItem__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n key: task.id,\n task: task,\n onTaskUpdate: onTaskUpdate,\n onTaskDelete: onTaskDelete,\n projects: projects\n });\n }) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-gray-500 dark:text-gray-400 text-center mt-4\"\n }, \"No tasks available.\"));\n};\n_c = TaskList;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TaskList);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"TaskList\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Task/TaskList.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Task/TaskModal.tsx": -/*!************************************************!*\ - !*** ./frontend/components/Task/TaskModal.tsx ***! - \************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _TaskActions__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./TaskActions */ \"./frontend/components/Task/TaskActions.tsx\");\n/* harmony import */ var _Shared_PriorityDropdown__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Shared/PriorityDropdown */ \"./frontend/components/Shared/PriorityDropdown.tsx\");\n/* harmony import */ var _Shared_StatusDropdown__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Shared/StatusDropdown */ \"./frontend/components/Shared/StatusDropdown.tsx\");\n/* harmony import */ var _Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../Shared/ConfirmDialog */ \"./frontend/components/Shared/ConfirmDialog.tsx\");\n/* harmony import */ var _Shared_ToastContext__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../Shared/ToastContext */ \"./frontend/components/Shared/ToastContext.tsx\");\n/* harmony import */ var _Tag_TagInput__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../Tag/TagInput */ \"./frontend/components/Tag/TagInput.tsx\");\n/* harmony import */ var _utils_tagsService__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../utils/tagsService */ \"./frontend/utils/tagsService.ts\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\n\n\n\n\nvar TaskModal = function TaskModal(_ref) {\n _s();\n var _task$tags, _formData$tags;\n var isOpen = _ref.isOpen,\n onClose = _ref.onClose,\n task = _ref.task,\n onSave = _ref.onSave,\n onDelete = _ref.onDelete,\n projects = _ref.projects,\n onCreateProject = _ref.onCreateProject;\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(task),\n _useState2 = _slicedToArray(_useState, 2),\n formData = _useState2[0],\n setFormData = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(((_task$tags = task.tags) === null || _task$tags === void 0 ? void 0 : _task$tags.map(function (tag) {\n return tag.name;\n })) || []),\n _useState4 = _slicedToArray(_useState3, 2),\n tags = _useState4[0],\n setTags = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(projects),\n _useState6 = _slicedToArray(_useState5, 2),\n filteredProjects = _useState6[0],\n setFilteredProjects = _useState6[1];\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(\"\"),\n _useState8 = _slicedToArray(_useState7, 2),\n newProjectName = _useState8[0],\n setNewProjectName = _useState8[1];\n var _useState9 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState10 = _slicedToArray(_useState9, 2),\n isCreatingProject = _useState10[0],\n setIsCreatingProject = _useState10[1];\n var _useState11 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState12 = _slicedToArray(_useState11, 2),\n dropdownOpen = _useState12[0],\n setDropdownOpen = _useState12[1];\n var modalRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n var _useState13 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState14 = _slicedToArray(_useState13, 2),\n isClosing = _useState14[0],\n setIsClosing = _useState14[1];\n var _useState15 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState16 = _slicedToArray(_useState15, 2),\n showConfirmDialog = _useState16[0],\n setShowConfirmDialog = _useState16[1];\n var _useState17 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)([]),\n _useState18 = _slicedToArray(_useState17, 2),\n localAvailableTags = _useState18[0],\n setLocalAvailableTags = _useState18[1];\n var _useState19 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState20 = _slicedToArray(_useState19, 2),\n tagsLoaded = _useState20[0],\n setTagsLoaded = _useState20[1];\n var _useState21 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState22 = _slicedToArray(_useState21, 2),\n tagsLoading = _useState22[0],\n setTagsLoading = _useState22[1];\n var _useToast = (0,_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_5__.useToast)(),\n showSuccessToast = _useToast.showSuccessToast,\n showErrorToast = _useToast.showErrorToast;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_8__.useTranslation)(),\n t = _useTranslation.t;\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var _task$tags2;\n setFormData(task);\n setTags(((_task$tags2 = task.tags) === null || _task$tags2 === void 0 ? void 0 : _task$tags2.map(function (tag) {\n return tag.name;\n })) || []);\n var currentProject = projects.find(function (project) {\n return project.id === task.project_id;\n });\n setNewProjectName(currentProject ? currentProject.name : '');\n }, [task, projects]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var loadTags = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var fetchedTags;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n if (!(isOpen && !tagsLoaded)) {\n _context.next = 17;\n break;\n }\n setTagsLoading(true);\n _context.prev = 2;\n _context.next = 5;\n return (0,_utils_tagsService__WEBPACK_IMPORTED_MODULE_7__.fetchTags)();\n case 5:\n fetchedTags = _context.sent;\n setLocalAvailableTags(fetchedTags);\n setTagsLoaded(true);\n _context.next = 14;\n break;\n case 10:\n _context.prev = 10;\n _context.t0 = _context[\"catch\"](2);\n console.error(\"Error fetching tags:\", _context.t0);\n setTagsLoaded(true); // Mark as loaded even on error to prevent retry loop\n case 14:\n _context.prev = 14;\n setTagsLoading(false);\n return _context.finish(14);\n case 17:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[2, 10, 14, 17]]);\n }));\n return function loadTags() {\n return _ref2.apply(this, arguments);\n };\n }();\n\n // Only load tags if modal is open\n if (isOpen) {\n loadTags();\n }\n }, [isOpen, tagsLoaded]);\n var handleChange = function handleChange(e) {\n var _e$target = e.target,\n name = _e$target.name,\n value = _e$target.value;\n setFormData(function (prev) {\n return _objectSpread(_objectSpread({}, prev), {}, _defineProperty({}, name, value));\n });\n };\n var handleTagsChange = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(function (newTags) {\n setTags(newTags);\n setFormData(function (prev) {\n return _objectSpread(_objectSpread({}, prev), {}, {\n tags: newTags.map(function (name) {\n return {\n name: name\n };\n })\n });\n });\n }, []);\n var handleProjectSearch = function handleProjectSearch(e) {\n var query = e.target.value.toLowerCase();\n setNewProjectName(query);\n setDropdownOpen(true);\n setFilteredProjects(projects.filter(function (project) {\n return project.name.toLowerCase().includes(query);\n }));\n };\n var handleProjectSelection = function handleProjectSelection(project) {\n setFormData(_objectSpread(_objectSpread({}, formData), {}, {\n project_id: project.id\n }));\n setNewProjectName(project.name);\n setDropdownOpen(false);\n };\n var handleCreateProject = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {\n var newProject;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n if (!(newProjectName.trim() !== \"\")) {\n _context2.next = 20;\n break;\n }\n setIsCreatingProject(true);\n _context2.prev = 2;\n _context2.next = 5;\n return onCreateProject(newProjectName);\n case 5:\n newProject = _context2.sent;\n setFormData(_objectSpread(_objectSpread({}, formData), {}, {\n project_id: newProject.id\n }));\n setFilteredProjects([].concat(_toConsumableArray(filteredProjects), [newProject]));\n setNewProjectName(newProject.name);\n setDropdownOpen(false);\n showSuccessToast(\"Project created successfully!\");\n _context2.next = 17;\n break;\n case 13:\n _context2.prev = 13;\n _context2.t0 = _context2[\"catch\"](2);\n showErrorToast(\"Failed to create project.\");\n console.error(\"Error creating project:\", _context2.t0);\n case 17:\n _context2.prev = 17;\n setIsCreatingProject(false);\n return _context2.finish(17);\n case 20:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, null, [[2, 13, 17, 20]]);\n }));\n return function handleCreateProject() {\n return _ref3.apply(this, arguments);\n };\n }();\n var handleSubmit = function handleSubmit() {\n onSave(_objectSpread(_objectSpread({}, formData), {}, {\n tags: tags.map(function (tag) {\n return {\n name: tag\n };\n })\n }));\n showSuccessToast(\"Task updated successfully!\");\n handleClose();\n };\n var handleDeleteClick = function handleDeleteClick() {\n setShowConfirmDialog(true);\n };\n var handleDeleteConfirm = function handleDeleteConfirm() {\n if (formData.id) {\n onDelete(formData.id);\n showSuccessToast(\"Task deleted successfully!\");\n setShowConfirmDialog(false);\n handleClose();\n }\n };\n var handleClose = function handleClose() {\n setIsClosing(true);\n setTimeout(function () {\n onClose();\n setIsClosing(false);\n setTagsLoaded(false); // Reset tags loaded state for next modal open\n }, 300);\n };\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n setFilteredProjects(projects);\n }, [projects]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleClickOutside = function handleClickOutside(event) {\n if (modalRef.current && !modalRef.current.contains(event.target)) {\n handleClose();\n }\n };\n if (isOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n }\n return function () {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, [isOpen]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n var handleKeyDown = function handleKeyDown(event) {\n if (event.key === \"Escape\") {\n handleClose();\n }\n };\n if (isOpen) {\n document.addEventListener(\"keydown\", handleKeyDown);\n }\n return function () {\n document.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [isOpen]);\n if (!isOpen) return null;\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"fixed top-16 left-0 right-0 bottom-0 flex items-start sm:items-center justify-center bg-gray-900 bg-opacity-80 z-40 transition-opacity duration-300 \".concat(isClosing ? \"opacity-0\" : \"opacity-100\")\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n ref: modalRef,\n className: \"bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-800 sm:rounded-lg sm:shadow-2xl w-full sm:max-w-3xl overflow-hidden transform transition-transform duration-300 \".concat(isClosing ? \"scale-95\" : \"scale-100\", \" h-screen sm:h-auto flex flex-col\"),\n style: {\n maxHeight: \"calc(100vh - 4rem)\"\n }\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"form\", {\n className: \"flex flex-col flex-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"fieldset\", {\n className: \"flex flex-col flex-1\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"p-4 space-y-3 flex-1 text-sm overflow-y-auto\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"py-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"text\",\n id: \"task_name_\".concat(task.id),\n name: \"name\",\n value: formData.name,\n onChange: handleChange,\n required: true,\n className: \"block w-full text-xl font-semibold dark:bg-gray-800 text-black dark:text-white border-b-2 border-gray-200 dark:border-gray-900 focus:outline-none shadow-sm py-2\",\n placeholder: t('forms.task.namePlaceholder', 'Add Task Name')\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"pb-3\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-xs font-medium text-gray-700 dark:text-gray-300 mb-2\"\n }, t('forms.task.labels.tags', 'Tags')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-full\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Tag_TagInput__WEBPACK_IMPORTED_MODULE_6__[\"default\"], {\n onTagsChange: handleTagsChange,\n initialTags: ((_formData$tags = formData.tags) === null || _formData$tags === void 0 ? void 0 : _formData$tags.map(function (tag) {\n return tag.name;\n })) || [],\n availableTags: localAvailableTags\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"pb-3 relative\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-xs font-medium text-gray-700 dark:text-gray-300 mb-3\"\n }, t('forms.task.labels.project', 'Project')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"text\",\n placeholder: t('forms.task.projectSearchPlaceholder', 'Search or create a project...'),\n value: newProjectName,\n onChange: handleProjectSearch,\n className: \"block w-full border border-gray-300 dark:border-gray-900 rounded-md focus:outline-none shadow-sm px-2 py-2 text-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100\"\n }), dropdownOpen && newProjectName && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"absolute mt-1 bg-white dark:bg-gray-900 shadow-md rounded-md w-full z-10\"\n }, filteredProjects.length > 0 ? filteredProjects.map(function (project) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n key: project.id,\n type: \"button\",\n onClick: function onClick() {\n return handleProjectSelection(project);\n },\n className: \"block w-full text-gray-500 dark:text-gray-300 text-left px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600\"\n }, project.name);\n }) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"px-4 py-2 text-gray-500 dark:text-gray-300\"\n }, t('forms.task.noMatchingProjects', 'No matching projects')), newProjectName && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: handleCreateProject,\n disabled: isCreatingProject,\n className: \"block w-full text-left px-4 py-2 bg-blue-500 text-white hover:bg-blue-600\"\n }, isCreatingProject ? t('forms.task.creatingProject', 'Creating...') : t('forms.task.createProject', '+ Create') + \" \\\"\".concat(newProjectName, \"\\\"\")))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"grid grid-cols-2 sm:grid-cols-3 gap-4 pb-3 sm:grid-flow-col\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-xs font-medium text-gray-700 dark:text-gray-300 mb-3\"\n }, t('forms.task.labels.status', 'Status')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Shared_StatusDropdown__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n value: formData.status,\n onChange: function onChange(value) {\n return setFormData(_objectSpread(_objectSpread({}, formData), {}, {\n status: value\n }));\n }\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-xs font-medium text-gray-700 dark:text-gray-300 mb-3\"\n }, t('forms.task.labels.priority', 'Priority')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Shared_PriorityDropdown__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n value: formData.priority || \"medium\",\n onChange: function onChange(value) {\n return setFormData(_objectSpread(_objectSpread({}, formData), {}, {\n priority: value\n }));\n }\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-xs font-medium text-gray-700 dark:text-gray-300 mb-3\"\n }, t('forms.task.labels.dueDate', 'Due Date')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"input\", {\n type: \"date\",\n id: \"task_due_date_\".concat(task.id),\n name: \"due_date\",\n value: formData.due_date || \"\",\n onChange: handleChange,\n className: \"block w-full focus:outline-none shadow-sm px-2 py-2 text-sm bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-900 rounded-md text-gray-900 dark:text-gray-100\"\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"pb-3\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"label\", {\n className: \"block text-xs font-medium text-gray-700 dark:text-gray-300 mb-3\"\n }, t('forms.noteContent')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"textarea\", {\n id: \"task_note_\".concat(task.id),\n name: \"note\",\n rows: 3,\n value: formData.note || \"\",\n onChange: handleChange,\n className: \"block w-full border border-gray-300 dark:border-gray-900 rounded-md focus:outline-none shadow-sm p-3 text-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100\",\n placeholder: t('forms.noteContentPlaceholder')\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"p-3 flex-shrink-0\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_TaskActions__WEBPACK_IMPORTED_MODULE_1__[\"default\"], {\n taskId: task.id,\n onDelete: handleDeleteClick,\n onSave: handleSubmit,\n onCancel: handleClose\n })))))), showConfirmDialog && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_Shared_ConfirmDialog__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n title: t('modals.deleteTask.title', 'Delete Task'),\n message: t('modals.deleteTask.confirmation', 'Are you sure you want to delete this task? This action cannot be undone.'),\n onConfirm: handleDeleteConfirm,\n onCancel: function onCancel() {\n return setShowConfirmDialog(false);\n }\n }));\n};\n_s(TaskModal, \"+Sq0XF3mMLcNvpHN4CJanEpbTmc=\", false, function () {\n return [_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_5__.useToast, react_i18next__WEBPACK_IMPORTED_MODULE_8__.useTranslation];\n});\n_c = TaskModal;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TaskModal);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"TaskModal\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Task/TaskModal.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Task/TaskPriorityIcon.tsx": -/*!*******************************************************!*\ - !*** ./frontend/components/Task/TaskPriorityIcon.tsx ***! - \*******************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/CheckCircleIcon.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\n\n\n\nvar TaskPriorityIcon = function TaskPriorityIcon(_ref) {\n _s();\n var priority = _ref.priority,\n status = _ref.status;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var getIconColor = function getIconColor() {\n if (status === 'done') return 'text-green-500';\n switch (priority) {\n case 'high':\n return 'text-red-500';\n case 'medium':\n return 'text-yellow-500';\n default:\n return 'text-gray-300';\n }\n };\n var colorClass = getIconColor();\n if (status === 'done') {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"h-5 w-5 \".concat(colorClass)\n });\n } else {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"svg\", {\n className: \"h-5 w-5 \".concat(colorClass),\n xmlns: \"http://www.w3.org/2000/svg\",\n fill: \"none\",\n viewBox: \"0 0 24 24\",\n stroke: \"currentColor\",\n strokeWidth: 2\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"circle\", {\n cx: \"12\",\n cy: \"12\",\n r: \"9\",\n stroke: \"currentColor\",\n strokeWidth: \"2\",\n fill: \"none\"\n }));\n }\n};\n_s(TaskPriorityIcon, \"zlIdU9EjM2llFt74AbE2KsUJXyM=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c = TaskPriorityIcon;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TaskPriorityIcon);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"TaskPriorityIcon\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Task/TaskPriorityIcon.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Task/TaskStatusBadge.tsx": -/*!******************************************************!*\ - !*** ./frontend/components/Task/TaskStatusBadge.tsx ***! - \******************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/MinusIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/ArrowPathIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/CheckCircleIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/ArchiveBoxIcon.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\n\n\n\nvar TaskStatusBadge = function TaskStatusBadge(_ref) {\n _s();\n var status = _ref.status,\n className = _ref.className;\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n var statusIcon, statusLabel;\n switch (status) {\n case 'not_started':\n statusIcon = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"h-4 w-4 text-gray-400\"\n });\n statusLabel = t('status.notStarted', 'Not Started');\n break;\n case 'in_progress':\n statusIcon = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n className: \"h-4 w-4 text-blue-400\"\n });\n statusLabel = t('status.inProgress', 'In Progress');\n break;\n case 'done':\n statusIcon = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_4__[\"default\"], {\n className: \"h-4 w-4 text-green-400\"\n });\n statusLabel = t('status.done', 'Done');\n break;\n case 'archived':\n statusIcon = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_5__[\"default\"], {\n className: \"h-4 w-4 text-gray-400\"\n });\n statusLabel = t('status.archived', 'Archived');\n break;\n default:\n statusIcon = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"h-4 w-4 text-gray-400\"\n });\n statusLabel = t('status.unknown', 'Unknown');\n }\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center md:px-2 \".concat(className)\n }, statusIcon);\n};\n_s(TaskStatusBadge, \"zlIdU9EjM2llFt74AbE2KsUJXyM=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation];\n});\n_c = TaskStatusBadge;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TaskStatusBadge);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"TaskStatusBadge\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Task/TaskStatusBadge.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Task/TaskTags.tsx": -/*!***********************************************!*\ - !*** ./frontend/components/Task/TaskTags.tsx ***! - \***********************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router/dist/index.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/TagIcon.js\");\n/* harmony import */ var _heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @heroicons/react/24/solid */ \"./node_modules/@heroicons/react/24/solid/esm/XMarkIcon.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nvar _s = __webpack_require__.$Refresh$.signature();\n\n\n\nvar TaskTags = function TaskTags(_ref) {\n _s();\n var _ref$tags = _ref.tags,\n tags = _ref$tags === void 0 ? [] : _ref$tags,\n onTagRemove = _ref.onTagRemove,\n className = _ref.className;\n var navigate = (0,react_router_dom__WEBPACK_IMPORTED_MODULE_1__.useNavigate)();\n var handleTagClick = function handleTagClick(tagName) {\n navigate(\"/tasks?tag=\".concat(tagName));\n };\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex flex-wrap gap-2 \".concat(className)\n }, tags.map(function (tag, index) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n key: tag.id || index,\n className: \"flex items-center bg-gray-200 text-gray-800 text-xs font-medium px-2 py-1.5 rounded-md dark:bg-gray-700 dark:text-gray-200 cursor-pointer\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: function onClick() {\n return handleTagClick(tag.name);\n },\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_2__[\"default\"], {\n className: \"hidden md:block h-4 w-4 text-gray-500 dark:text-gray-300 mr-2\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"text-xs text-gray-700 dark:text-gray-300\"\n }, tag.name)), onTagRemove && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"button\", {\n type: \"button\",\n onClick: function onClick() {\n return onTagRemove(tag.id);\n },\n className: \"ml-1 text-gray-500 hover:text-gray-700 dark:hover:text-gray-400 focus:outline-none\",\n \"aria-label\": \"Remove tag \".concat(tag.name)\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_solid__WEBPACK_IMPORTED_MODULE_3__[\"default\"], {\n className: \"h-4 w-4\"\n })));\n }));\n};\n_s(TaskTags, \"CzcTeTziyjMsSrAVmHuCCb6+Bfg=\", false, function () {\n return [react_router_dom__WEBPACK_IMPORTED_MODULE_1__.useNavigate];\n});\n_c = TaskTags;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TaskTags);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"TaskTags\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Task/TaskTags.tsx?"); - -/***/ }), - -/***/ "./frontend/components/Task/TasksToday.tsx": -/*!*************************************************!*\ - !*** ./frontend/components/Task/TasksToday.tsx ***! - \*************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! date-fns */ \"./node_modules/date-fns/format.js\");\n/* harmony import */ var date_fns_locale__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! date-fns/locale */ \"./node_modules/date-fns/locale/el.js\");\n/* harmony import */ var date_fns_locale__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! date-fns/locale */ \"./node_modules/date-fns/locale/es.js\");\n/* harmony import */ var date_fns_locale__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! date-fns/locale */ \"./node_modules/date-fns/locale/ja.js\");\n/* harmony import */ var date_fns_locale__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! date-fns/locale */ \"./node_modules/date-fns/locale/uk.js\");\n/* harmony import */ var date_fns_locale__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! date-fns/locale */ \"./node_modules/date-fns/locale/de.js\");\n/* harmony import */ var date_fns_locale__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! date-fns/locale */ \"./node_modules/date-fns/locale/en-US.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* harmony import */ var i18next__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! i18next */ \"./node_modules/i18next/dist/esm/i18next.js\");\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router-dom/dist/index.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/CalendarDaysIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/ClipboardDocumentListIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/ArrowPathIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/ClockIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/FolderIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/ArchiveBoxIcon.js\");\n/* harmony import */ var _heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! @heroicons/react/24/outline */ \"./node_modules/@heroicons/react/24/outline/esm/InboxIcon.js\");\n/* harmony import */ var _utils_tasksService__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../utils/tasksService */ \"./frontend/utils/tasksService.ts\");\n/* harmony import */ var _utils_projectsService__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../utils/projectsService */ \"./frontend/utils/projectsService.ts\");\n/* harmony import */ var _utils_inboxService__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../utils/inboxService */ \"./frontend/utils/inboxService.ts\");\n/* harmony import */ var _store_useStore__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../store/useStore */ \"./frontend/store/useStore.ts\");\n/* harmony import */ var _TaskList__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./TaskList */ \"./frontend/components/Task/TaskList.tsx\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nvar _s = __webpack_require__.$Refresh$.signature();\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }\nfunction _nonIterableRest() { throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction _iterableToArrayLimit(r, l) { var t = null == r ? null : \"undefined\" != typeof Symbol && r[Symbol.iterator] || r[\"@@iterator\"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t[\"return\"] && (u = t[\"return\"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }\nfunction _arrayWithHoles(r) { if (Array.isArray(r)) return r; }\n\n\n\n\n\n\n\n\n\n\n\n\nvar getLocale = function getLocale(language) {\n switch (language) {\n case 'el':\n return date_fns_locale__WEBPACK_IMPORTED_MODULE_8__.el;\n case 'es':\n return date_fns_locale__WEBPACK_IMPORTED_MODULE_9__.es;\n case 'jp':\n return date_fns_locale__WEBPACK_IMPORTED_MODULE_10__.ja;\n case 'ua':\n return date_fns_locale__WEBPACK_IMPORTED_MODULE_11__.uk;\n case 'de':\n return date_fns_locale__WEBPACK_IMPORTED_MODULE_12__.de;\n default:\n return date_fns_locale__WEBPACK_IMPORTED_MODULE_13__.enUS;\n }\n};\nvar TasksToday = function TasksToday() {\n _s();\n var _useTranslation = (0,react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation)(),\n t = _useTranslation.t;\n\n // Don't use multiple separate useStore calls - combine them into one\n var store = (0,_store_useStore__WEBPACK_IMPORTED_MODULE_6__.useStore)();\n\n // Use local state for data instead of directly using store state\n // This prevents unnecessary re-renders from store updates\n var _useState = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)([]),\n _useState2 = _slicedToArray(_useState, 2),\n localTasks = _useState2[0],\n setLocalTasks = _useState2[1];\n var _useState3 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)([]),\n _useState4 = _slicedToArray(_useState3, 2),\n localProjects = _useState4[0],\n setLocalProjects = _useState4[1];\n var _useState5 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState6 = _slicedToArray(_useState5, 2),\n isLoading = _useState6[0],\n setIsLoading = _useState6[1];\n var _useState7 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false),\n _useState8 = _slicedToArray(_useState7, 2),\n isError = _useState8[0],\n setIsError = _useState8[1];\n\n // Metrics from the API\n var _useState9 = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)({\n total_open_tasks: 0,\n tasks_pending_over_month: 0,\n tasks_in_progress_count: 0,\n tasks_in_progress: [],\n tasks_due_today: [],\n suggested_tasks: []\n }),\n _useState10 = _slicedToArray(_useState9, 2),\n metrics = _useState10[0],\n setMetrics = _useState10[1];\n\n // Track mounting state to prevent state updates after unmount\n var isMounted = react__WEBPACK_IMPORTED_MODULE_0___default().useRef(false);\n\n // Load data once on component mount\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(function () {\n isMounted.current = true;\n\n // Only fetch data once on mount\n var loadData = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var projectsData, _yield$fetchTasks, fetchedTasks, fetchedMetrics;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n if (isMounted.current) {\n _context.next = 2;\n break;\n }\n return _context.abrupt(\"return\");\n case 2:\n setIsLoading(true);\n setIsError(false);\n try {\n // Load inbox items to ensure the notification appears correctly\n (0,_utils_inboxService__WEBPACK_IMPORTED_MODULE_5__.loadInboxItemsToStore)();\n } catch (error) {\n console.error(\"Failed to load inbox items:\", error);\n }\n _context.prev = 5;\n _context.next = 8;\n return (0,_utils_projectsService__WEBPACK_IMPORTED_MODULE_4__.fetchProjects)();\n case 8:\n projectsData = _context.sent;\n if (isMounted.current) {\n setLocalProjects(projectsData);\n // Also update the store\n store.projectsStore.setProjects(projectsData);\n }\n _context.next = 16;\n break;\n case 12:\n _context.prev = 12;\n _context.t0 = _context[\"catch\"](5);\n console.error(\"Failed to fetch projects:\", _context.t0);\n if (isMounted.current) {\n setIsError(true);\n }\n case 16:\n _context.prev = 16;\n _context.next = 19;\n return (0,_utils_tasksService__WEBPACK_IMPORTED_MODULE_3__.fetchTasks)(\"?type=today\");\n case 19:\n _yield$fetchTasks = _context.sent;\n fetchedTasks = _yield$fetchTasks.tasks;\n fetchedMetrics = _yield$fetchTasks.metrics;\n if (isMounted.current) {\n setLocalTasks(fetchedTasks);\n setMetrics(fetchedMetrics);\n // Also update the store\n store.tasksStore.setTasks(fetchedTasks);\n }\n _context.next = 29;\n break;\n case 25:\n _context.prev = 25;\n _context.t1 = _context[\"catch\"](16);\n console.error(\"Failed to fetch tasks:\", _context.t1);\n if (isMounted.current) {\n setIsError(true);\n }\n case 29:\n _context.prev = 29;\n if (isMounted.current) {\n setIsLoading(false);\n }\n return _context.finish(29);\n case 32:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[5, 12], [16, 25, 29, 32]]);\n }));\n return function loadData() {\n return _ref.apply(this, arguments);\n };\n }();\n loadData();\n\n // Cleanup function to prevent state updates after unmount\n return function () {\n isMounted.current = false;\n };\n }, []); // Empty dependency array - only run once on mount\n\n // Memoize task handlers to prevent recreating functions on each render\n var handleTaskUpdate = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(/*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(updatedTask) {\n var _yield$fetchTasks2, updatedTasks, _metrics;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n if (!(!updatedTask.id || !isMounted.current)) {\n _context2.next = 2;\n break;\n }\n return _context2.abrupt(\"return\");\n case 2:\n setIsLoading(true);\n _context2.prev = 3;\n _context2.next = 6;\n return (0,_utils_tasksService__WEBPACK_IMPORTED_MODULE_3__.updateTask)(updatedTask.id, updatedTask);\n case 6:\n _context2.next = 8;\n return (0,_utils_tasksService__WEBPACK_IMPORTED_MODULE_3__.fetchTasks)(\"?type=today\");\n case 8:\n _yield$fetchTasks2 = _context2.sent;\n updatedTasks = _yield$fetchTasks2.tasks;\n _metrics = _yield$fetchTasks2.metrics;\n if (isMounted.current) {\n setLocalTasks(updatedTasks);\n setMetrics(_metrics);\n // Update store\n store.tasksStore.setTasks(updatedTasks);\n }\n _context2.next = 18;\n break;\n case 14:\n _context2.prev = 14;\n _context2.t0 = _context2[\"catch\"](3);\n console.error(\"Error updating task:\", _context2.t0);\n if (isMounted.current) {\n setIsError(true);\n }\n case 18:\n _context2.prev = 18;\n if (isMounted.current) {\n setIsLoading(false);\n }\n return _context2.finish(18);\n case 21:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, null, [[3, 14, 18, 21]]);\n }));\n return function (_x) {\n return _ref2.apply(this, arguments);\n };\n }(), [store.tasksStore]);\n var handleTaskDelete = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(/*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(taskId) {\n var _yield$fetchTasks3, updatedTasks, _metrics2;\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n if (isMounted.current) {\n _context3.next = 2;\n break;\n }\n return _context3.abrupt(\"return\");\n case 2:\n setIsLoading(true);\n _context3.prev = 3;\n _context3.next = 6;\n return (0,_utils_tasksService__WEBPACK_IMPORTED_MODULE_3__.deleteTask)(taskId);\n case 6:\n _context3.next = 8;\n return (0,_utils_tasksService__WEBPACK_IMPORTED_MODULE_3__.fetchTasks)(\"?type=today\");\n case 8:\n _yield$fetchTasks3 = _context3.sent;\n updatedTasks = _yield$fetchTasks3.tasks;\n _metrics2 = _yield$fetchTasks3.metrics;\n if (isMounted.current) {\n setLocalTasks(updatedTasks);\n setMetrics(_metrics2);\n // Update store\n store.tasksStore.setTasks(updatedTasks);\n }\n _context3.next = 18;\n break;\n case 14:\n _context3.prev = 14;\n _context3.t0 = _context3[\"catch\"](3);\n console.error(\"Error deleting task:\", _context3.t0);\n if (isMounted.current) {\n setIsError(true);\n }\n case 18:\n _context3.prev = 18;\n if (isMounted.current) {\n setIsLoading(false);\n }\n return _context3.finish(18);\n case 21:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3, null, [[3, 14, 18, 21]]);\n }));\n return function (_x2) {\n return _ref3.apply(this, arguments);\n };\n }(), [store.tasksStore]);\n\n // Get inbox items count from store for the notification\n var inboxItemsCount = store.inboxStore.inboxItems.length;\n\n // Show loading state\n if (isLoading && localTasks.length === 0) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex justify-center items-center h-64\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-gray-500 dark:text-gray-400\"\n }, t('common.loading', 'Loading...')));\n }\n\n // Show error state\n if (isError && localTasks.length === 0) {\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex justify-center items-center h-64\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-red-500\"\n }, t('errors.somethingWentWrong', 'Something went wrong')));\n }\n return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex justify-center px-4 lg:px-2\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"w-full max-w-5xl\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center mb-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h2\", {\n className: \"text-2xl font-light flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_14__[\"default\"], {\n className: \"h-5 w-5 mr-2\"\n }), \" \", t('tasks.today')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"span\", {\n className: \"ml-4 text-gray-500\"\n }, (0,date_fns__WEBPACK_IMPORTED_MODULE_15__.format)(new Date(), \"PPP\", {\n locale: getLocale(i18next__WEBPACK_IMPORTED_MODULE_2__[\"default\"].language)\n }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-6 grid grid-cols-1 sm:grid-cols-2 gap-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"bg-white dark:bg-gray-900 rounded-lg shadow p-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h3\", {\n className: \"text-lg font-medium mb-3 text-gray-700 dark:text-gray-300\"\n }, t('tasks.metrics', 'Tasks')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"grid grid-cols-2 gap-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"space-y-3\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-between\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_16__[\"default\"], {\n className: \"h-6 w-6 text-blue-500 mr-3\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-sm text-gray-500 dark:text-gray-400\"\n }, t('tasks.backlog'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-xl font-semibold\"\n }, metrics.total_open_tasks)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-between\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_17__[\"default\"], {\n className: \"h-6 w-6 text-green-500 mr-3\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-sm text-gray-500 dark:text-gray-400\"\n }, t('tasks.inProgress'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-xl font-semibold\"\n }, metrics.tasks_in_progress_count))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"space-y-3\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-between\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_14__[\"default\"], {\n className: \"h-6 w-6 text-red-500 mr-3\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-sm text-gray-500 dark:text-gray-400\"\n }, t('tasks.dueToday'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-xl font-semibold\"\n }, metrics.tasks_due_today.length)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-between\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_18__[\"default\"], {\n className: \"h-6 w-6 text-yellow-500 mr-3\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-sm text-gray-500 dark:text-gray-400\"\n }, t('tasks.stale'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-xl font-semibold\"\n }, metrics.tasks_pending_over_month))))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"bg-white dark:bg-gray-900 rounded-lg shadow p-4\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h3\", {\n className: \"text-lg font-medium mb-3 text-gray-700 dark:text-gray-300\"\n }, t('projects.metrics', 'Projects')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"space-y-3\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-between\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_19__[\"default\"], {\n className: \"h-6 w-6 text-blue-500 mr-3\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-sm text-gray-500 dark:text-gray-400\"\n }, t('projects.active'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-xl font-semibold\"\n }, localProjects.filter(function (project) {\n return project.active;\n }).length)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center justify-between\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_20__[\"default\"], {\n className: \"h-6 w-6 text-gray-500 mr-3\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-sm text-gray-500 dark:text-gray-400\"\n }, t('projects.inactive'))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-xl font-semibold\"\n }, localProjects.filter(function (project) {\n return !project.active;\n }).length))))), inboxItemsCount > 0 && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", {\n className: \"mb-6 p-4 bg-white dark:bg-gray-900 border-l-4 border-blue-500 rounded-lg shadow\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_21__.Link, {\n to: \"/inbox\",\n className: \"flex items-center\"\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_heroicons_react_24_outline__WEBPACK_IMPORTED_MODULE_22__[\"default\"], {\n className: \"h-6 w-6 text-blue-500 dark:text-blue-400 mr-3\"\n }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"div\", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-gray-700 dark:text-gray-300 font-medium\"\n }, t('inbox.unprocessedItems', {\n count: inboxItemsCount,\n defaultValue: \"You have \".concat(inboxItemsCount, \" item(s) in your inbox.\")\n })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-blue-600 dark:text-blue-400 text-sm\"\n }, t('inbox.processNow', 'Process them now'))))), metrics.tasks_due_today.length > 0 && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h3\", {\n className: \"text-xl font-medium mt-6 mb-2\"\n }, t('tasks.dueToday')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_TaskList__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n tasks: metrics.tasks_due_today,\n onTaskUpdate: handleTaskUpdate,\n onTaskDelete: handleTaskDelete,\n projects: localProjects\n })), metrics.tasks_in_progress.length > 0 && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h3\", {\n className: \"text-xl font-medium mt-6 mb-2\"\n }, t('tasks.inProgress')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_TaskList__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n tasks: metrics.tasks_in_progress,\n onTaskUpdate: handleTaskUpdate,\n onTaskDelete: handleTaskDelete,\n projects: localProjects\n })), metrics.suggested_tasks.length > 0 && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"h3\", {\n className: \"text-xl font-medium mt-6 mb-2\"\n }, t('tasks.suggested')), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_TaskList__WEBPACK_IMPORTED_MODULE_7__[\"default\"], {\n tasks: metrics.suggested_tasks,\n onTaskUpdate: handleTaskUpdate,\n onTaskDelete: handleTaskDelete,\n projects: localProjects\n })), localTasks.length === 0 && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(\"p\", {\n className: \"text-gray-500 text-center mt-4\"\n }, t('tasks.noTasksAvailable'))));\n};\n_s(TasksToday, \"Pp7XCDK90/f6bRCgAJBd2Sk00Jk=\", false, function () {\n return [react_i18next__WEBPACK_IMPORTED_MODULE_1__.useTranslation, _store_useStore__WEBPACK_IMPORTED_MODULE_6__.useStore];\n});\n_c = TasksToday;\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (TasksToday);\nvar _c;\n__webpack_require__.$Refresh$.register(_c, \"TasksToday\");\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/components/Task/TasksToday.tsx?"); - -/***/ }), - -/***/ "./frontend/i18n.ts": -/*!**************************!*\ - !*** ./frontend/i18n.ts ***! - \**************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var i18next__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! i18next */ \"./node_modules/i18next/dist/esm/i18next.js\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* harmony import */ var i18next_http_backend__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! i18next-http-backend */ \"./node_modules/i18next-http-backend/esm/index.js\");\n/* harmony import */ var i18next_browser_languagedetector__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! i18next-browser-languagedetector */ \"./node_modules/i18next-browser-languagedetector/dist/esm/i18nextBrowserLanguageDetector.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\n\n\n\n\nvar isDevelopment = \"development\" === 'development';\nvar fallbackResources = {\n en: {\n translation: {\n common: {\n loading: 'Loading...',\n appLoading: 'Loading application... Please wait.',\n error: 'Error'\n },\n auth: {\n login: 'Login',\n register: 'Register'\n },\n errors: {\n somethingWentWrong: 'Something went wrong, please try again'\n }\n }\n }\n};\nvar devResources = isDevelopment ? {\n en: {\n translation: fallbackResources.en.translation\n }\n} : undefined;\nvar i18nInstance = i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].use(i18next_http_backend__WEBPACK_IMPORTED_MODULE_2__[\"default\"]).use(i18next_browser_languagedetector__WEBPACK_IMPORTED_MODULE_3__[\"default\"]).use(react_i18next__WEBPACK_IMPORTED_MODULE_1__.initReactI18next);\ni18nInstance.init({\n fallbackLng: 'en',\n debug: isDevelopment,\n load: 'languageOnly',\n supportedLngs: ['en', 'es', 'el', 'jp', 'ua', 'de'],\n nonExplicitSupportedLngs: true,\n resources: devResources,\n detection: {\n order: ['querystring', 'cookie', 'localStorage', 'navigator'],\n lookupQuerystring: 'lng',\n lookupCookie: 'i18next',\n lookupLocalStorage: 'i18nextLng',\n caches: ['localStorage', 'cookie']\n },\n interpolation: {\n escapeValue: false\n },\n defaultNS: 'translation',\n ns: ['translation'],\n backend: {\n loadPath: '/locales/{{lng}}/{{ns}}.json',\n queryStringParams: {\n v: '1'\n },\n requestOptions: {\n cache: 'default',\n credentials: 'same-origin',\n mode: 'cors'\n }\n }\n}).then(function () {\n var loadPath = isDevelopment ? \"./locales/\".concat(i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].language, \"/translation.json\") : \"/locales/\".concat(i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].language, \"/translation.json\");\n fetch(loadPath).then(function (response) {\n if (!response.ok) {\n if (isDevelopment) {\n return fetch(\"/locales/\".concat(i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].language, \"/translation.json\"));\n }\n throw new Error(\"Failed to fetch translation: \".concat(response.status));\n }\n return response.json();\n }).then(function (data) {\n i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].addResourceBundle(i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].language, 'translation', data, true, true);\n })[\"catch\"](function () {\n if (isDevelopment) {\n try {\n setTimeout(function () {\n fetch(\"/locales/\".concat(i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].language, \"/translation.json\"), {\n headers: {\n 'Accept': 'application/json'\n },\n mode: 'cors'\n }).then(function (res) {\n return res.json();\n }).then(function (data) {\n i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].addResourceBundle(i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].language, 'translation', data, true, true);\n })[\"catch\"](function () {});\n }, 1000);\n } catch (e) {}\n }\n });\n});\ni18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].on('initialized', function () {});\ni18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].on('loaded', function () {});\ni18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].on('failedLoading', function () {});\ni18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].on('missingKey', function () {});\nvar dispatchLanguageChangeEvent = function dispatchLanguageChangeEvent(lng) {\n var event = new CustomEvent('app-language-changed', {\n detail: {\n language: lng\n }\n });\n window.dispatchEvent(event);\n};\ni18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].on('languageChanged', function (lng) {\n localStorage.setItem('i18nextLng', lng);\n document.documentElement.lang = lng;\n var handleTranslationsLoaded = function handleTranslationsLoaded() {\n dispatchLanguageChangeEvent(lng);\n if (i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].services && i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].services.resourceStore) {\n var currentNS = i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].options.defaultNS || 'translation';\n i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].reloadResources(lng, currentNS);\n }\n };\n if (!i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].hasResourceBundle(lng, 'translation')) {\n var loadPath = isDevelopment ? \"./locales/\".concat(lng, \"/translation.json\") : \"/locales/\".concat(lng, \"/translation.json\");\n fetch(loadPath).then(function (response) {\n if (!response.ok) {\n return fetch(\"/locales/\".concat(lng, \"/translation.json\"));\n }\n return response;\n }).then(function (response) {\n return response.json();\n }).then(function (data) {\n if (data) {\n i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].addResourceBundle(lng, 'translation', data, true, true);\n handleTranslationsLoaded();\n }\n })[\"catch\"](function () {\n handleTranslationsLoaded();\n });\n } else {\n handleTranslationsLoaded();\n }\n});\nwindow.checkTranslation = function (key) {\n try {\n var translation = i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].t(key);\n return translation;\n } catch (_unused) {\n return null;\n }\n};\nwindow.forceLanguageReload = function (lng) {\n var targetLng = lng || i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].language;\n i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].reloadResources(targetLng, 'translation').then(function () {\n dispatchLanguageChangeEvent(targetLng);\n if (i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].services && i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].services.resourceStore) {\n Object.values(i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].services.resourceStore.data).forEach(function (lang) {\n if (lang.translation && _typeof(lang.translation) === 'object' && lang.translation !== null) {\n var temp = _objectSpread({}, lang.translation);\n lang.translation = temp;\n }\n });\n }\n if (lng) {\n setTimeout(function () {\n i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"].changeLanguage(targetLng);\n }, 50);\n }\n })[\"catch\"](function () {});\n};\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (i18next__WEBPACK_IMPORTED_MODULE_0__[\"default\"]);\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/i18n.ts?"); - -/***/ }), - -/***/ "./frontend/index.tsx": -/*!****************************!*\ - !*** ./frontend/index.tsx ***! - \****************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_dom_client__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-dom/client */ \"./node_modules/react-dom/client.js\");\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! react-router-dom */ \"./node_modules/react-router-dom/dist/index.js\");\n/* harmony import */ var _App__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./App */ \"./frontend/App.tsx\");\n/* harmony import */ var _components_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./components/Shared/ToastContext */ \"./frontend/components/Shared/ToastContext.tsx\");\n/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./i18n */ \"./frontend/i18n.ts\");\n/* harmony import */ var react_i18next__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! react-i18next */ \"./node_modules/react-i18next/dist/es/index.js\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\n// Add type declaration for module.hot\n\n\n\n\n\n\n // Import i18n config to initialize it\n\n // Import the i18n instance with its configuration\n\nvar storedPreference = localStorage.getItem(\"isDarkMode\");\nvar prefersDarkMode = window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\nvar isDarkMode = storedPreference ? storedPreference === \"true\" : prefersDarkMode;\nif (isDarkMode) {\n document.documentElement.classList.add(\"dark\");\n} else {\n document.documentElement.classList.remove(\"dark\");\n}\nvar container = document.getElementById(\"root\");\n\n// Store the root outside the if block so it can be accessed by the HMR code\nvar root;\nif (container) {\n root = (0,react_dom_client__WEBPACK_IMPORTED_MODULE_1__.createRoot)(container);\n root.render(/*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_i18next__WEBPACK_IMPORTED_MODULE_5__.I18nextProvider, {\n i18n: _i18n__WEBPACK_IMPORTED_MODULE_4__[\"default\"]\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_6__.BrowserRouter, null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_3__.ToastProvider, null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_App__WEBPACK_IMPORTED_MODULE_2__[\"default\"], null)))));\n}\n\n// Hot Module Replacement (HMR) - Remove this snippet to remove HMR.\n// Learn more: https://www.webpackjs.com/concepts/hot-module-replacement/\nif (true) {\n module.hot.accept(/*! ./App */ \"./frontend/App.tsx\", __WEBPACK_OUTDATED_DEPENDENCIES__ => { /* harmony import */ _App__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./App */ \"./frontend/App.tsx\");\n(function () {\n // New version of App component imported\n if (root) {\n root.render(/*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_i18next__WEBPACK_IMPORTED_MODULE_5__.I18nextProvider, {\n i18n: _i18n__WEBPACK_IMPORTED_MODULE_4__[\"default\"]\n }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_6__.BrowserRouter, null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_components_Shared_ToastContext__WEBPACK_IMPORTED_MODULE_3__.ToastProvider, null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_App__WEBPACK_IMPORTED_MODULE_2__[\"default\"], null)))));\n }\n })(__WEBPACK_OUTDATED_DEPENDENCIES__); });\n}\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/index.tsx?"); - -/***/ }), - -/***/ "./frontend/store/useStore.ts": -/*!************************************!*\ - !*** ./frontend/store/useStore.ts ***! - \************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ useStore: () => (/* binding */ useStore)\n/* harmony export */ });\n/* harmony import */ var zustand__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! zustand */ \"./node_modules/zustand/esm/react.mjs\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\nfunction _unsupportedIterableToArray(r, a) { if (r) { if (\"string\" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }\nfunction _iterableToArray(r) { if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r); }\nfunction _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }\nfunction _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n\nvar useStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__.create)(function (set) {\n return {\n notesStore: {\n notes: [],\n isLoading: false,\n isError: false,\n setNotes: function setNotes(notes) {\n return set(function (state) {\n return {\n notesStore: _objectSpread(_objectSpread({}, state.notesStore), {}, {\n notes: notes\n })\n };\n });\n },\n setLoading: function setLoading(isLoading) {\n return set(function (state) {\n return {\n notesStore: _objectSpread(_objectSpread({}, state.notesStore), {}, {\n isLoading: isLoading\n })\n };\n });\n },\n setError: function setError(isError) {\n return set(function (state) {\n return {\n notesStore: _objectSpread(_objectSpread({}, state.notesStore), {}, {\n isError: isError\n })\n };\n });\n }\n },\n areasStore: {\n areas: [],\n isLoading: false,\n isError: false,\n setAreas: function setAreas(areas) {\n return set(function (state) {\n return {\n areasStore: _objectSpread(_objectSpread({}, state.areasStore), {}, {\n areas: areas\n })\n };\n });\n },\n setLoading: function setLoading(isLoading) {\n return set(function (state) {\n return {\n areasStore: _objectSpread(_objectSpread({}, state.areasStore), {}, {\n isLoading: isLoading\n })\n };\n });\n },\n setError: function setError(isError) {\n return set(function (state) {\n return {\n areasStore: _objectSpread(_objectSpread({}, state.areasStore), {}, {\n isError: isError\n })\n };\n });\n }\n },\n projectsStore: {\n projects: [],\n isLoading: false,\n isError: false,\n setProjects: function setProjects(projects) {\n return set(function (state) {\n return {\n projectsStore: _objectSpread(_objectSpread({}, state.projectsStore), {}, {\n projects: projects\n })\n };\n });\n },\n setLoading: function setLoading(isLoading) {\n return set(function (state) {\n return {\n projectsStore: _objectSpread(_objectSpread({}, state.projectsStore), {}, {\n isLoading: isLoading\n })\n };\n });\n },\n setError: function setError(isError) {\n return set(function (state) {\n return {\n projectsStore: _objectSpread(_objectSpread({}, state.projectsStore), {}, {\n isError: isError\n })\n };\n });\n }\n },\n tagsStore: {\n tags: [],\n isLoading: false,\n isError: false,\n setTags: function setTags(tags) {\n return set(function (state) {\n return {\n tagsStore: _objectSpread(_objectSpread({}, state.tagsStore), {}, {\n tags: tags\n })\n };\n });\n },\n setLoading: function setLoading(isLoading) {\n return set(function (state) {\n return {\n tagsStore: _objectSpread(_objectSpread({}, state.tagsStore), {}, {\n isLoading: isLoading\n })\n };\n });\n },\n setError: function setError(isError) {\n return set(function (state) {\n return {\n tagsStore: _objectSpread(_objectSpread({}, state.tagsStore), {}, {\n isError: isError\n })\n };\n });\n }\n },\n tasksStore: {\n tasks: [],\n isLoading: false,\n isError: false,\n setTasks: function setTasks(tasks) {\n return set(function (state) {\n return {\n tasksStore: _objectSpread(_objectSpread({}, state.tasksStore), {}, {\n tasks: tasks\n })\n };\n });\n },\n setLoading: function setLoading(isLoading) {\n return set(function (state) {\n return {\n tasksStore: _objectSpread(_objectSpread({}, state.tasksStore), {}, {\n isLoading: isLoading\n })\n };\n });\n },\n setError: function setError(isError) {\n return set(function (state) {\n return {\n tasksStore: _objectSpread(_objectSpread({}, state.tasksStore), {}, {\n isError: isError\n })\n };\n });\n }\n },\n inboxStore: {\n inboxItems: [],\n isLoading: false,\n isError: false,\n setInboxItems: function setInboxItems(inboxItems) {\n return set(function (state) {\n return {\n inboxStore: _objectSpread(_objectSpread({}, state.inboxStore), {}, {\n inboxItems: inboxItems\n })\n };\n });\n },\n addInboxItem: function addInboxItem(inboxItem) {\n return set(function (state) {\n return {\n inboxStore: _objectSpread(_objectSpread({}, state.inboxStore), {}, {\n inboxItems: [].concat(_toConsumableArray(state.inboxStore.inboxItems), [inboxItem])\n })\n };\n });\n },\n updateInboxItem: function updateInboxItem(inboxItem) {\n return set(function (state) {\n return {\n inboxStore: _objectSpread(_objectSpread({}, state.inboxStore), {}, {\n inboxItems: state.inboxStore.inboxItems.map(function (item) {\n return item.id === inboxItem.id ? inboxItem : item;\n })\n })\n };\n });\n },\n removeInboxItem: function removeInboxItem(id) {\n return set(function (state) {\n return {\n inboxStore: _objectSpread(_objectSpread({}, state.inboxStore), {}, {\n inboxItems: state.inboxStore.inboxItems.filter(function (item) {\n return item.id !== id;\n })\n })\n };\n });\n },\n setLoading: function setLoading(isLoading) {\n return set(function (state) {\n return {\n inboxStore: _objectSpread(_objectSpread({}, state.inboxStore), {}, {\n isLoading: isLoading\n })\n };\n });\n },\n setError: function setError(isError) {\n return set(function (state) {\n return {\n inboxStore: _objectSpread(_objectSpread({}, state.inboxStore), {}, {\n isError: isError\n })\n };\n });\n }\n }\n };\n});\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/store/useStore.ts?"); - -/***/ }), - -/***/ "./frontend/utils/areasService.ts": -/*!****************************************!*\ - !*** ./frontend/utils/areasService.ts ***! - \****************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ createArea: () => (/* binding */ createArea),\n/* harmony export */ deleteArea: () => (/* binding */ deleteArea),\n/* harmony export */ fetchAreas: () => (/* binding */ fetchAreas),\n/* harmony export */ updateArea: () => (/* binding */ updateArea)\n/* harmony export */ });\n/* harmony import */ var _authUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./authUtils */ \"./frontend/utils/authUtils.ts\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\n\nvar fetchAreas = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var response;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.next = 2;\n return fetch(\"/api/areas?active=true\", {\n credentials: 'include',\n headers: {\n 'Accept': 'application/json'\n }\n });\n case 2:\n response = _context.sent;\n _context.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to fetch areas.');\n case 5:\n _context.next = 7;\n return response.json();\n case 7:\n return _context.abrupt(\"return\", _context.sent);\n case 8:\n case \"end\":\n return _context.stop();\n }\n }, _callee);\n }));\n return function fetchAreas() {\n return _ref.apply(this, arguments);\n };\n}();\nvar createArea = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(areaData) {\n var response;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n _context2.next = 2;\n return fetch('/api/areas', {\n method: 'POST',\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json'\n },\n body: JSON.stringify(areaData)\n });\n case 2:\n response = _context2.sent;\n _context2.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to create area.');\n case 5:\n _context2.next = 7;\n return response.json();\n case 7:\n return _context2.abrupt(\"return\", _context2.sent);\n case 8:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2);\n }));\n return function createArea(_x) {\n return _ref2.apply(this, arguments);\n };\n}();\nvar updateArea = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(areaId, areaData) {\n var response;\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n _context3.next = 2;\n return fetch(\"/api/areas/\".concat(areaId), {\n method: 'PATCH',\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json'\n },\n body: JSON.stringify(areaData)\n });\n case 2:\n response = _context3.sent;\n _context3.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to update area.');\n case 5:\n _context3.next = 7;\n return response.json();\n case 7:\n return _context3.abrupt(\"return\", _context3.sent);\n case 8:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3);\n }));\n return function updateArea(_x2, _x3) {\n return _ref3.apply(this, arguments);\n };\n}();\nvar deleteArea = /*#__PURE__*/function () {\n var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4(areaId) {\n var response;\n return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n while (1) switch (_context4.prev = _context4.next) {\n case 0:\n _context4.next = 2;\n return fetch(\"/api/areas/\".concat(areaId), {\n method: 'DELETE',\n credentials: 'include',\n headers: {\n 'Accept': 'application/json'\n }\n });\n case 2:\n response = _context4.sent;\n _context4.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to delete area.');\n case 5:\n case \"end\":\n return _context4.stop();\n }\n }, _callee4);\n }));\n return function deleteArea(_x4) {\n return _ref4.apply(this, arguments);\n };\n}();\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/utils/areasService.ts?"); - -/***/ }), - -/***/ "./frontend/utils/authUtils.ts": -/*!*************************************!*\ - !*** ./frontend/utils/authUtils.ts ***! - \*************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ getDefaultHeaders: () => (/* binding */ getDefaultHeaders),\n/* harmony export */ getPostHeaders: () => (/* binding */ getPostHeaders),\n/* harmony export */ handleAuthResponse: () => (/* binding */ handleAuthResponse),\n/* harmony export */ isAuthError: () => (/* binding */ isAuthError)\n/* harmony export */ });\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\nfunction ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }\nfunction _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }\nfunction _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }\nfunction _toPropertyKey(t) { var i = _toPrimitive(t, \"string\"); return \"symbol\" == _typeof(i) ? i : i + \"\"; }\nfunction _toPrimitive(t, r) { if (\"object\" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || \"default\"); if (\"object\" != _typeof(i)) return i; throw new TypeError(\"@@toPrimitive must return a primitive value.\"); } return (\"string\" === r ? String : Number)(t); }\n/**\n * Get default headers for API requests including CSRF protection\n */\nvar getDefaultHeaders = function getDefaultHeaders() {\n return {\n 'Accept': 'application/json',\n 'X-Requested-With': 'XMLHttpRequest',\n 'Origin': window.location.origin\n };\n};\n\n/**\n * Get default headers for POST/PATCH requests\n */\nvar getPostHeaders = function getPostHeaders() {\n return _objectSpread(_objectSpread({}, getDefaultHeaders()), {}, {\n 'Content-Type': 'application/json'\n });\n};\n\n// Global flag to prevent multiple simultaneous redirects\nvar isRedirecting = false;\n\n/**\n * Handles authentication errors by redirecting to login page\n * @param response - The fetch response object\n * @param errorMessage - Default error message to throw if not a 401\n * @returns Promise that resolves if response is ok, rejects with error if not\n */\nvar handleAuthResponse = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(response, errorMessage) {\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n if (response.ok) {\n _context.next = 5;\n break;\n }\n if (!(response.status === 401)) {\n _context.next = 4;\n break;\n }\n // Check if we're already on the login page or already redirecting to avoid redirect loops\n if (window.location.pathname !== '/login' && !isRedirecting) {\n console.log('Authentication required, redirecting to login');\n isRedirecting = true;\n // Add a small delay to allow any pending operations to complete\n setTimeout(function () {\n window.location.href = '/login';\n }, 100);\n }\n throw new Error('Authentication required');\n case 4:\n throw new Error(errorMessage);\n case 5:\n return _context.abrupt(\"return\", response);\n case 6:\n case \"end\":\n return _context.stop();\n }\n }, _callee);\n }));\n return function handleAuthResponse(_x, _x2) {\n return _ref.apply(this, arguments);\n };\n}();\n\n/**\n * Checks if an error is an authentication error\n * @param error - The error to check\n * @returns true if it's an authentication error\n */\nvar isAuthError = function isAuthError(error) {\n return (error === null || error === void 0 ? void 0 : error.message) && error.message.includes('Authentication required');\n};\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/utils/authUtils.ts?"); - -/***/ }), - -/***/ "./frontend/utils/inboxService.ts": -/*!****************************************!*\ - !*** ./frontend/utils/inboxService.ts ***! - \****************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ createInboxItem: () => (/* binding */ createInboxItem),\n/* harmony export */ createInboxItemWithStore: () => (/* binding */ createInboxItemWithStore),\n/* harmony export */ deleteInboxItem: () => (/* binding */ deleteInboxItem),\n/* harmony export */ deleteInboxItemWithStore: () => (/* binding */ deleteInboxItemWithStore),\n/* harmony export */ fetchInboxItems: () => (/* binding */ fetchInboxItems),\n/* harmony export */ loadInboxItemsToStore: () => (/* binding */ loadInboxItemsToStore),\n/* harmony export */ processInboxItem: () => (/* binding */ processInboxItem),\n/* harmony export */ processInboxItemWithStore: () => (/* binding */ processInboxItemWithStore),\n/* harmony export */ updateInboxItem: () => (/* binding */ updateInboxItem),\n/* harmony export */ updateInboxItemWithStore: () => (/* binding */ updateInboxItemWithStore)\n/* harmony export */ });\n/* harmony import */ var _store_useStore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../store/useStore */ \"./frontend/store/useStore.ts\");\n/* harmony import */ var _authUtils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./authUtils */ \"./frontend/utils/authUtils.ts\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\n\n\n\n// API functions\nvar fetchInboxItems = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var response, result;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.next = 2;\n return fetch('/api/inbox', {\n credentials: 'include',\n headers: {\n 'Accept': 'application/json'\n }\n });\n case 2:\n response = _context.sent;\n _context.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_1__.handleAuthResponse)(response, 'Failed to fetch inbox items.');\n case 5:\n _context.next = 7;\n return response.json();\n case 7:\n result = _context.sent;\n if (Array.isArray(result)) {\n _context.next = 10;\n break;\n }\n throw new Error('Resulting inbox items are not an array.');\n case 10:\n return _context.abrupt(\"return\", result);\n case 11:\n case \"end\":\n return _context.stop();\n }\n }, _callee);\n }));\n return function fetchInboxItems() {\n return _ref.apply(this, arguments);\n };\n}();\nvar createInboxItem = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(content) {\n var source,\n response,\n _args2 = arguments;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n source = _args2.length > 1 && _args2[1] !== undefined ? _args2[1] : 'tududi';\n _context2.next = 3;\n return fetch('/api/inbox', {\n method: 'POST',\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json'\n },\n body: JSON.stringify({\n content: content,\n source: source\n })\n });\n case 3:\n response = _context2.sent;\n _context2.next = 6;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_1__.handleAuthResponse)(response, 'Failed to create inbox item.');\n case 6:\n _context2.next = 8;\n return response.json();\n case 8:\n return _context2.abrupt(\"return\", _context2.sent);\n case 9:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2);\n }));\n return function createInboxItem(_x) {\n return _ref2.apply(this, arguments);\n };\n}();\nvar updateInboxItem = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(itemId, content) {\n var response;\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n _context3.next = 2;\n return fetch(\"/api/inbox/\".concat(itemId), {\n method: 'PATCH',\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json'\n },\n body: JSON.stringify({\n content: content\n })\n });\n case 2:\n response = _context3.sent;\n _context3.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_1__.handleAuthResponse)(response, 'Failed to update inbox item.');\n case 5:\n _context3.next = 7;\n return response.json();\n case 7:\n return _context3.abrupt(\"return\", _context3.sent);\n case 8:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3);\n }));\n return function updateInboxItem(_x2, _x3) {\n return _ref3.apply(this, arguments);\n };\n}();\nvar processInboxItem = /*#__PURE__*/function () {\n var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4(itemId) {\n var response;\n return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n while (1) switch (_context4.prev = _context4.next) {\n case 0:\n _context4.next = 2;\n return fetch(\"/api/inbox/\".concat(itemId, \"/process\"), {\n method: 'PATCH',\n credentials: 'include',\n headers: {\n 'Accept': 'application/json'\n }\n });\n case 2:\n response = _context4.sent;\n _context4.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_1__.handleAuthResponse)(response, 'Failed to process inbox item.');\n case 5:\n _context4.next = 7;\n return response.json();\n case 7:\n return _context4.abrupt(\"return\", _context4.sent);\n case 8:\n case \"end\":\n return _context4.stop();\n }\n }, _callee4);\n }));\n return function processInboxItem(_x4) {\n return _ref4.apply(this, arguments);\n };\n}();\nvar deleteInboxItem = /*#__PURE__*/function () {\n var _ref5 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee5(itemId) {\n var response;\n return _regeneratorRuntime().wrap(function _callee5$(_context5) {\n while (1) switch (_context5.prev = _context5.next) {\n case 0:\n _context5.next = 2;\n return fetch(\"/api/inbox/\".concat(itemId), {\n method: 'DELETE',\n credentials: 'include',\n headers: {\n 'Accept': 'application/json'\n }\n });\n case 2:\n response = _context5.sent;\n _context5.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_1__.handleAuthResponse)(response, 'Failed to delete inbox item.');\n case 5:\n case \"end\":\n return _context5.stop();\n }\n }, _callee5);\n }));\n return function deleteInboxItem(_x5) {\n return _ref5.apply(this, arguments);\n };\n}();\n\n// Track last check time to detect new items\nvar lastCheckTimestamp = Date.now();\n\n// Store-aware functions\nvar loadInboxItemsToStore = /*#__PURE__*/function () {\n var _ref6 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee6() {\n var inboxStore, items, currentItemIds, currentTime, newTelegramItems, notificationData;\n return _regeneratorRuntime().wrap(function _callee6$(_context6) {\n while (1) switch (_context6.prev = _context6.next) {\n case 0:\n inboxStore = _store_useStore__WEBPACK_IMPORTED_MODULE_0__.useStore.getState().inboxStore; // Only show loading for initial load\n if (inboxStore.inboxItems.length === 0) {\n inboxStore.setLoading(true);\n }\n _context6.prev = 2;\n _context6.next = 5;\n return fetchInboxItems();\n case 5:\n items = _context6.sent;\n // Check for new items since last check\n currentItemIds = new Set(inboxStore.inboxItems.map(function (item) {\n return item.id;\n }));\n currentTime = Date.now(); // New telegram items\n newTelegramItems = items.filter(function (item) {\n return item.id && !currentItemIds.has(item.id) && item.source === 'telegram';\n }); // Only show notifications if we have detected changes\n if (inboxStore.inboxItems.length > 0 && newTelegramItems.length > 0) {\n // Instead of trying to show toast directly (which won't work outside of React components),\n // dispatch a custom event that the component can listen for and show toasts\n // Get some minimal info about the items for the notification\n notificationData = {\n count: newTelegramItems.length,\n firstItemContent: newTelegramItems[0].content.substring(0, 30) + (newTelegramItems[0].content.length > 30 ? '...' : '')\n }; // Dispatch a custom event with the notification data\n window.dispatchEvent(new CustomEvent('inboxItemsUpdated', {\n detail: notificationData\n }));\n }\n\n // Update state and timestamp\n inboxStore.setInboxItems(items);\n inboxStore.setError(false);\n lastCheckTimestamp = currentTime;\n _context6.next = 19;\n break;\n case 15:\n _context6.prev = 15;\n _context6.t0 = _context6[\"catch\"](2);\n console.error('Failed to load inbox items:', _context6.t0);\n inboxStore.setError(true);\n case 19:\n _context6.prev = 19;\n inboxStore.setLoading(false);\n return _context6.finish(19);\n case 22:\n case \"end\":\n return _context6.stop();\n }\n }, _callee6, null, [[2, 15, 19, 22]]);\n }));\n return function loadInboxItemsToStore() {\n return _ref6.apply(this, arguments);\n };\n}();\nvar createInboxItemWithStore = /*#__PURE__*/function () {\n var _ref7 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee7(content) {\n var source,\n inboxStore,\n newItem,\n _args7 = arguments;\n return _regeneratorRuntime().wrap(function _callee7$(_context7) {\n while (1) switch (_context7.prev = _context7.next) {\n case 0:\n source = _args7.length > 1 && _args7[1] !== undefined ? _args7[1] : 'tududi';\n inboxStore = _store_useStore__WEBPACK_IMPORTED_MODULE_0__.useStore.getState().inboxStore;\n _context7.prev = 2;\n _context7.next = 5;\n return createInboxItem(content, source);\n case 5:\n newItem = _context7.sent;\n inboxStore.addInboxItem(newItem);\n return _context7.abrupt(\"return\", newItem);\n case 10:\n _context7.prev = 10;\n _context7.t0 = _context7[\"catch\"](2);\n console.error('Failed to create inbox item:', _context7.t0);\n throw _context7.t0;\n case 14:\n case \"end\":\n return _context7.stop();\n }\n }, _callee7, null, [[2, 10]]);\n }));\n return function createInboxItemWithStore(_x6) {\n return _ref7.apply(this, arguments);\n };\n}();\nvar updateInboxItemWithStore = /*#__PURE__*/function () {\n var _ref8 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee8(itemId, content) {\n var inboxStore, updatedItem;\n return _regeneratorRuntime().wrap(function _callee8$(_context8) {\n while (1) switch (_context8.prev = _context8.next) {\n case 0:\n inboxStore = _store_useStore__WEBPACK_IMPORTED_MODULE_0__.useStore.getState().inboxStore;\n _context8.prev = 1;\n _context8.next = 4;\n return updateInboxItem(itemId, content);\n case 4:\n updatedItem = _context8.sent;\n inboxStore.updateInboxItem(updatedItem);\n return _context8.abrupt(\"return\", updatedItem);\n case 9:\n _context8.prev = 9;\n _context8.t0 = _context8[\"catch\"](1);\n console.error('Failed to update inbox item:', _context8.t0);\n throw _context8.t0;\n case 13:\n case \"end\":\n return _context8.stop();\n }\n }, _callee8, null, [[1, 9]]);\n }));\n return function updateInboxItemWithStore(_x7, _x8) {\n return _ref8.apply(this, arguments);\n };\n}();\nvar processInboxItemWithStore = /*#__PURE__*/function () {\n var _ref9 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee9(itemId) {\n var inboxStore, processedItem;\n return _regeneratorRuntime().wrap(function _callee9$(_context9) {\n while (1) switch (_context9.prev = _context9.next) {\n case 0:\n inboxStore = _store_useStore__WEBPACK_IMPORTED_MODULE_0__.useStore.getState().inboxStore;\n _context9.prev = 1;\n _context9.next = 4;\n return processInboxItem(itemId);\n case 4:\n processedItem = _context9.sent;\n inboxStore.removeInboxItem(itemId);\n return _context9.abrupt(\"return\", processedItem);\n case 9:\n _context9.prev = 9;\n _context9.t0 = _context9[\"catch\"](1);\n console.error('Failed to process inbox item:', _context9.t0);\n throw _context9.t0;\n case 13:\n case \"end\":\n return _context9.stop();\n }\n }, _callee9, null, [[1, 9]]);\n }));\n return function processInboxItemWithStore(_x9) {\n return _ref9.apply(this, arguments);\n };\n}();\nvar deleteInboxItemWithStore = /*#__PURE__*/function () {\n var _ref10 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee10(itemId) {\n var inboxStore;\n return _regeneratorRuntime().wrap(function _callee10$(_context10) {\n while (1) switch (_context10.prev = _context10.next) {\n case 0:\n inboxStore = _store_useStore__WEBPACK_IMPORTED_MODULE_0__.useStore.getState().inboxStore;\n _context10.prev = 1;\n _context10.next = 4;\n return deleteInboxItem(itemId);\n case 4:\n inboxStore.removeInboxItem(itemId);\n _context10.next = 11;\n break;\n case 7:\n _context10.prev = 7;\n _context10.t0 = _context10[\"catch\"](1);\n console.error('Failed to delete inbox item:', _context10.t0);\n throw _context10.t0;\n case 11:\n case \"end\":\n return _context10.stop();\n }\n }, _callee10, null, [[1, 7]]);\n }));\n return function deleteInboxItemWithStore(_x10) {\n return _ref10.apply(this, arguments);\n };\n}();\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/utils/inboxService.ts?"); - -/***/ }), - -/***/ "./frontend/utils/notesService.ts": -/*!****************************************!*\ - !*** ./frontend/utils/notesService.ts ***! - \****************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ createNote: () => (/* binding */ createNote),\n/* harmony export */ deleteNote: () => (/* binding */ deleteNote),\n/* harmony export */ fetchNotes: () => (/* binding */ fetchNotes),\n/* harmony export */ updateNote: () => (/* binding */ updateNote)\n/* harmony export */ });\n/* harmony import */ var _authUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./authUtils */ \"./frontend/utils/authUtils.ts\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\n\nvar fetchNotes = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var response;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.next = 2;\n return fetch(\"/api/notes\", {\n credentials: 'include',\n headers: (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.getDefaultHeaders)()\n });\n case 2:\n response = _context.sent;\n _context.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to fetch notes.');\n case 5:\n _context.next = 7;\n return response.json();\n case 7:\n return _context.abrupt(\"return\", _context.sent);\n case 8:\n case \"end\":\n return _context.stop();\n }\n }, _callee);\n }));\n return function fetchNotes() {\n return _ref.apply(this, arguments);\n };\n}();\nvar createNote = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(noteData) {\n var response;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n _context2.prev = 0;\n console.log(\"Creating note with data:\", JSON.stringify(noteData, null, 2));\n _context2.next = 4;\n return fetch('/api/note', {\n method: 'POST',\n credentials: 'include',\n headers: (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.getPostHeaders)(),\n body: JSON.stringify(noteData)\n });\n case 4:\n response = _context2.sent;\n _context2.next = 7;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to create note.');\n case 7:\n _context2.next = 9;\n return response.json();\n case 9:\n return _context2.abrupt(\"return\", _context2.sent);\n case 12:\n _context2.prev = 12;\n _context2.t0 = _context2[\"catch\"](0);\n console.error(\"Exception in createNote:\", _context2.t0);\n throw _context2.t0;\n case 16:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, null, [[0, 12]]);\n }));\n return function createNote(_x) {\n return _ref2.apply(this, arguments);\n };\n}();\nvar updateNote = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(noteId, noteData) {\n var response;\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n _context3.next = 2;\n return fetch(\"/api/note/\".concat(noteId), {\n method: 'PATCH',\n credentials: 'include',\n headers: (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.getPostHeaders)(),\n body: JSON.stringify(noteData)\n });\n case 2:\n response = _context3.sent;\n _context3.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to update note.');\n case 5:\n _context3.next = 7;\n return response.json();\n case 7:\n return _context3.abrupt(\"return\", _context3.sent);\n case 8:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3);\n }));\n return function updateNote(_x2, _x3) {\n return _ref3.apply(this, arguments);\n };\n}();\nvar deleteNote = /*#__PURE__*/function () {\n var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4(noteId) {\n var response;\n return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n while (1) switch (_context4.prev = _context4.next) {\n case 0:\n _context4.next = 2;\n return fetch(\"/api/note/\".concat(noteId), {\n method: 'DELETE',\n credentials: 'include',\n headers: (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.getDefaultHeaders)()\n });\n case 2:\n response = _context4.sent;\n _context4.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to delete note.');\n case 5:\n case \"end\":\n return _context4.stop();\n }\n }, _callee4);\n }));\n return function deleteNote(_x4) {\n return _ref4.apply(this, arguments);\n };\n}();\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/utils/notesService.ts?"); - -/***/ }), - -/***/ "./frontend/utils/projectsService.ts": -/*!*******************************************!*\ - !*** ./frontend/utils/projectsService.ts ***! - \*******************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ createProject: () => (/* binding */ createProject),\n/* harmony export */ deleteProject: () => (/* binding */ deleteProject),\n/* harmony export */ fetchProjectById: () => (/* binding */ fetchProjectById),\n/* harmony export */ fetchProjects: () => (/* binding */ fetchProjects),\n/* harmony export */ updateProject: () => (/* binding */ updateProject)\n/* harmony export */ });\n/* harmony import */ var _authUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./authUtils */ \"./frontend/utils/authUtils.ts\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\n\nvar fetchProjects = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var activeFilter,\n areaFilter,\n url,\n params,\n response,\n data,\n _args = arguments;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n activeFilter = _args.length > 0 && _args[0] !== undefined ? _args[0] : \"all\";\n areaFilter = _args.length > 1 && _args[1] !== undefined ? _args[1] : \"\";\n url = \"/api/projects\";\n params = new URLSearchParams();\n if (activeFilter !== \"all\") params.append(\"active\", activeFilter);\n if (areaFilter) params.append(\"area_id\", areaFilter);\n if (params.toString()) url += \"?\".concat(params.toString());\n _context.next = 9;\n return fetch(url, {\n credentials: 'include',\n headers: {\n Accept: 'application/json'\n }\n });\n case 9:\n response = _context.sent;\n _context.next = 12;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to fetch projects.');\n case 12:\n _context.next = 14;\n return response.json();\n case 14:\n data = _context.sent;\n return _context.abrupt(\"return\", data.projects || data);\n case 16:\n case \"end\":\n return _context.stop();\n }\n }, _callee);\n }));\n return function fetchProjects() {\n return _ref.apply(this, arguments);\n };\n}();\nvar fetchProjectById = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(projectId) {\n var response;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n _context2.next = 2;\n return fetch(\"/api/project/\".concat(projectId), {\n credentials: 'include',\n headers: {\n Accept: 'application/json'\n }\n });\n case 2:\n response = _context2.sent;\n _context2.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to fetch project details.');\n case 5:\n _context2.next = 7;\n return response.json();\n case 7:\n return _context2.abrupt(\"return\", _context2.sent);\n case 8:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2);\n }));\n return function fetchProjectById(_x) {\n return _ref2.apply(this, arguments);\n };\n}();\nvar createProject = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(projectData) {\n var response;\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n _context3.next = 2;\n return fetch('/api/project', {\n method: 'POST',\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json'\n },\n body: JSON.stringify(projectData)\n });\n case 2:\n response = _context3.sent;\n _context3.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to create project.');\n case 5:\n _context3.next = 7;\n return response.json();\n case 7:\n return _context3.abrupt(\"return\", _context3.sent);\n case 8:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3);\n }));\n return function createProject(_x2) {\n return _ref3.apply(this, arguments);\n };\n}();\nvar updateProject = /*#__PURE__*/function () {\n var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4(projectId, projectData) {\n var response;\n return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n while (1) switch (_context4.prev = _context4.next) {\n case 0:\n _context4.next = 2;\n return fetch(\"/api/project/\".concat(projectId), {\n method: 'PATCH',\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json'\n },\n body: JSON.stringify(projectData)\n });\n case 2:\n response = _context4.sent;\n _context4.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to update project.');\n case 5:\n _context4.next = 7;\n return response.json();\n case 7:\n return _context4.abrupt(\"return\", _context4.sent);\n case 8:\n case \"end\":\n return _context4.stop();\n }\n }, _callee4);\n }));\n return function updateProject(_x3, _x4) {\n return _ref4.apply(this, arguments);\n };\n}();\nvar deleteProject = /*#__PURE__*/function () {\n var _ref5 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee5(projectId) {\n var response;\n return _regeneratorRuntime().wrap(function _callee5$(_context5) {\n while (1) switch (_context5.prev = _context5.next) {\n case 0:\n _context5.next = 2;\n return fetch(\"/api/project/\".concat(projectId), {\n method: 'DELETE',\n credentials: 'include',\n headers: {\n 'Accept': 'application/json'\n }\n });\n case 2:\n response = _context5.sent;\n _context5.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to delete project.');\n case 5:\n case \"end\":\n return _context5.stop();\n }\n }, _callee5);\n }));\n return function deleteProject(_x5) {\n return _ref5.apply(this, arguments);\n };\n}();\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/utils/projectsService.ts?"); - -/***/ }), - -/***/ "./frontend/utils/tagsService.ts": -/*!***************************************!*\ - !*** ./frontend/utils/tagsService.ts ***! - \***************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ createTag: () => (/* binding */ createTag),\n/* harmony export */ deleteTag: () => (/* binding */ deleteTag),\n/* harmony export */ fetchTags: () => (/* binding */ fetchTags),\n/* harmony export */ updateTag: () => (/* binding */ updateTag)\n/* harmony export */ });\n/* harmony import */ var _authUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./authUtils */ \"./frontend/utils/authUtils.ts\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\n\nvar fetchTags = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var response;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.prev = 0;\n _context.next = 3;\n return fetch(\"/api/tags\", {\n credentials: 'include',\n headers: {\n 'Accept': 'application/json',\n 'Cache-Control': 'no-cache',\n 'Pragma': 'no-cache'\n }\n });\n case 3:\n response = _context.sent;\n _context.next = 6;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to fetch tags.');\n case 6:\n _context.next = 8;\n return response.json();\n case 8:\n return _context.abrupt(\"return\", _context.sent);\n case 11:\n _context.prev = 11;\n _context.t0 = _context[\"catch\"](0);\n console.error(\"Tags fetch error:\", _context.t0);\n // Return empty array to prevent UI from breaking\n return _context.abrupt(\"return\", []);\n case 15:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[0, 11]]);\n }));\n return function fetchTags() {\n return _ref.apply(this, arguments);\n };\n}();\nvar createTag = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(tagData) {\n var response;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n _context2.next = 2;\n return fetch('/api/tag', {\n method: 'POST',\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json'\n },\n body: JSON.stringify(tagData)\n });\n case 2:\n response = _context2.sent;\n _context2.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to create tag.');\n case 5:\n _context2.next = 7;\n return response.json();\n case 7:\n return _context2.abrupt(\"return\", _context2.sent);\n case 8:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2);\n }));\n return function createTag(_x) {\n return _ref2.apply(this, arguments);\n };\n}();\nvar updateTag = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(tagId, tagData) {\n var response;\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n _context3.next = 2;\n return fetch(\"/api/tag/\".concat(tagId), {\n method: 'PATCH',\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json'\n },\n body: JSON.stringify(tagData)\n });\n case 2:\n response = _context3.sent;\n _context3.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to update tag.');\n case 5:\n _context3.next = 7;\n return response.json();\n case 7:\n return _context3.abrupt(\"return\", _context3.sent);\n case 8:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3);\n }));\n return function updateTag(_x2, _x3) {\n return _ref3.apply(this, arguments);\n };\n}();\nvar deleteTag = /*#__PURE__*/function () {\n var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4(tagId) {\n var response;\n return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n while (1) switch (_context4.prev = _context4.next) {\n case 0:\n _context4.next = 2;\n return fetch(\"/api/tag/\".concat(tagId), {\n method: 'DELETE',\n credentials: 'include',\n headers: {\n 'Accept': 'application/json'\n }\n });\n case 2:\n response = _context4.sent;\n _context4.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to delete tag.');\n case 5:\n case \"end\":\n return _context4.stop();\n }\n }, _callee4);\n }));\n return function deleteTag(_x4) {\n return _ref4.apply(this, arguments);\n };\n}();\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/utils/tagsService.ts?"); - -/***/ }), - -/***/ "./frontend/utils/tasksService.ts": -/*!****************************************!*\ - !*** ./frontend/utils/tasksService.ts ***! - \****************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ createTask: () => (/* binding */ createTask),\n/* harmony export */ deleteTask: () => (/* binding */ deleteTask),\n/* harmony export */ fetchTasks: () => (/* binding */ fetchTasks),\n/* harmony export */ updateTask: () => (/* binding */ updateTask)\n/* harmony export */ });\n/* harmony import */ var _authUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./authUtils */ \"./frontend/utils/authUtils.ts\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\n\nvar fetchTasks = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {\n var query,\n response,\n result,\n _args = arguments;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n query = _args.length > 0 && _args[0] !== undefined ? _args[0] : '';\n _context.next = 3;\n return fetch(\"/api/tasks\".concat(query), {\n credentials: 'include',\n headers: (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.getDefaultHeaders)()\n });\n case 3:\n response = _context.sent;\n _context.next = 6;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to fetch tasks.');\n case 6:\n _context.next = 8;\n return response.json();\n case 8:\n result = _context.sent;\n if (Array.isArray(result.tasks)) {\n _context.next = 11;\n break;\n }\n throw new Error('Resulting tasks are not an array.');\n case 11:\n if (result.metrics) {\n _context.next = 13;\n break;\n }\n throw new Error('Metrics data is not included.');\n case 13:\n return _context.abrupt(\"return\", {\n tasks: result.tasks,\n metrics: result.metrics\n });\n case 14:\n case \"end\":\n return _context.stop();\n }\n }, _callee);\n }));\n return function fetchTasks() {\n return _ref.apply(this, arguments);\n };\n}();\nvar createTask = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(taskData) {\n var response;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n _context2.next = 2;\n return fetch('/api/task', {\n method: 'POST',\n credentials: 'include',\n headers: (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.getPostHeaders)(),\n body: JSON.stringify(taskData)\n });\n case 2:\n response = _context2.sent;\n _context2.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to create task.');\n case 5:\n _context2.next = 7;\n return response.json();\n case 7:\n return _context2.abrupt(\"return\", _context2.sent);\n case 8:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2);\n }));\n return function createTask(_x) {\n return _ref2.apply(this, arguments);\n };\n}();\nvar updateTask = /*#__PURE__*/function () {\n var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(taskId, taskData) {\n var response;\n return _regeneratorRuntime().wrap(function _callee3$(_context3) {\n while (1) switch (_context3.prev = _context3.next) {\n case 0:\n _context3.next = 2;\n return fetch(\"/api/task/\".concat(taskId), {\n method: 'PATCH',\n credentials: 'include',\n headers: (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.getPostHeaders)(),\n body: JSON.stringify(taskData)\n });\n case 2:\n response = _context3.sent;\n _context3.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to update task.');\n case 5:\n _context3.next = 7;\n return response.json();\n case 7:\n return _context3.abrupt(\"return\", _context3.sent);\n case 8:\n case \"end\":\n return _context3.stop();\n }\n }, _callee3);\n }));\n return function updateTask(_x2, _x3) {\n return _ref3.apply(this, arguments);\n };\n}();\nvar deleteTask = /*#__PURE__*/function () {\n var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4(taskId) {\n var response;\n return _regeneratorRuntime().wrap(function _callee4$(_context4) {\n while (1) switch (_context4.prev = _context4.next) {\n case 0:\n _context4.next = 2;\n return fetch(\"/api/task/\".concat(taskId), {\n method: 'DELETE',\n credentials: 'include',\n headers: (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.getDefaultHeaders)()\n });\n case 2:\n response = _context4.sent;\n _context4.next = 5;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to delete task.');\n case 5:\n case \"end\":\n return _context4.stop();\n }\n }, _callee4);\n }));\n return function deleteTask(_x4) {\n return _ref4.apply(this, arguments);\n };\n}();\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/utils/tasksService.ts?"); - -/***/ }), - -/***/ "./frontend/utils/urlService.ts": -/*!**************************************!*\ - !*** ./frontend/utils/urlService.ts ***! - \**************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ extractTitleFromText: () => (/* binding */ extractTitleFromText),\n/* harmony export */ extractUrlTitle: () => (/* binding */ extractUrlTitle),\n/* harmony export */ isUrl: () => (/* binding */ isUrl)\n/* harmony export */ });\n/* harmony import */ var _authUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./authUtils */ \"./frontend/utils/authUtils.ts\");\n/* provided dependency */ var __react_refresh_utils__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js\");\n/* provided dependency */ var __react_refresh_error_overlay__ = __webpack_require__(/*! ./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js */ \"./node_modules/@pmmmwh/react-refresh-webpack-plugin/overlay/index.js\");\n__webpack_require__.$Refresh$.runtime = __webpack_require__(/*! ./node_modules/react-refresh/runtime.js */ \"./node_modules/react-refresh/runtime.js\");\n\nfunction _typeof(o) { \"@babel/helpers - typeof\"; return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o; }, _typeof(o); }\nfunction _regeneratorRuntime() { \"use strict\"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = \"function\" == typeof Symbol ? Symbol : {}, a = i.iterator || \"@@iterator\", c = i.asyncIterator || \"@@asyncIterator\", u = i.toStringTag || \"@@toStringTag\"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, \"\"); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, \"_invoke\", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: \"normal\", arg: t.call(e, r) }; } catch (t) { return { type: \"throw\", arg: t }; } } e.wrap = wrap; var h = \"suspendedStart\", l = \"suspendedYield\", f = \"executing\", s = \"completed\", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { [\"next\", \"throw\", \"return\"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if (\"throw\" !== c.type) { var u = c.arg, h = u.value; return h && \"object\" == _typeof(h) && n.call(h, \"__await\") ? e.resolve(h.__await).then(function (t) { invoke(\"next\", t, i, a); }, function (t) { invoke(\"throw\", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke(\"throw\", t, i, a); }); } a(c.arg); } var r; o(this, \"_invoke\", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error(\"Generator is already running\"); if (o === s) { if (\"throw\" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if (\"next\" === n.method) n.sent = n._sent = n.arg;else if (\"throw\" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else \"return\" === n.method && n.abrupt(\"return\", n.arg); o = f; var p = tryCatch(e, r, n); if (\"normal\" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } \"throw\" === p.type && (o = s, n.method = \"throw\", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, \"throw\" === n && e.iterator[\"return\"] && (r.method = \"return\", r.arg = t, maybeInvokeDelegate(e, r), \"throw\" === r.method) || \"return\" !== n && (r.method = \"throw\", r.arg = new TypeError(\"The iterator does not provide a '\" + n + \"' method\")), y; var i = tryCatch(o, e.iterator, r.arg); if (\"throw\" === i.type) return r.method = \"throw\", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, \"return\" !== r.method && (r.method = \"next\", r.arg = t), r.delegate = null, y) : a : (r.method = \"throw\", r.arg = new TypeError(\"iterator result is not an object\"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = \"normal\", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: \"root\" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || \"\" === e) { var r = e[a]; if (r) return r.call(e); if (\"function\" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + \" is not iterable\"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, \"constructor\", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, \"constructor\", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, \"GeneratorFunction\"), e.isGeneratorFunction = function (t) { var e = \"function\" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || \"GeneratorFunction\" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, \"GeneratorFunction\")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, \"Generator\"), define(g, a, function () { return this; }), define(g, \"toString\", function () { return \"[object Generator]\"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = \"next\", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) \"t\" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if (\"throw\" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = \"throw\", a.arg = e, r.next = n, o && (r.method = \"next\", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if (\"root\" === i.tryLoc) return handle(\"end\"); if (i.tryLoc <= this.prev) { var c = n.call(i, \"catchLoc\"), u = n.call(i, \"finallyLoc\"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error(\"try statement without catch or finally\"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, \"finallyLoc\") && this.prev < o.finallyLoc) { var i = o; break; } } i && (\"break\" === t || \"continue\" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = \"next\", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if (\"throw\" === t.type) throw t.arg; return \"break\" === t.type || \"continue\" === t.type ? this.next = t.arg : \"return\" === t.type ? (this.rval = this.arg = t.arg, this.method = \"return\", this.next = \"end\") : \"normal\" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, \"catch\": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if (\"throw\" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error(\"illegal catch attempt\"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, \"next\" === this.method && (this.arg = t), y; } }, e; }\nfunction asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }\nfunction _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"next\", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, \"throw\", n); } _next(void 0); }); }; }\n/**\n * Service for URL-related operations like extracting titles from web pages\n */\n\n/**\n * Extract the title of a web page from its URL\n * @param url The URL to extract the title from\n * @returns Promise resolving to the page title or null if not found\n */\nvar extractUrlTitle = /*#__PURE__*/function () {\n var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(url) {\n var response;\n return _regeneratorRuntime().wrap(function _callee$(_context) {\n while (1) switch (_context.prev = _context.next) {\n case 0:\n _context.prev = 0;\n _context.next = 3;\n return fetch(\"/api/url/title?url=\".concat(encodeURIComponent(url)), {\n credentials: 'include',\n headers: {\n 'Accept': 'application/json'\n }\n });\n case 3:\n response = _context.sent;\n _context.next = 6;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to extract URL title');\n case 6:\n _context.next = 8;\n return response.json();\n case 8:\n return _context.abrupt(\"return\", _context.sent);\n case 11:\n _context.prev = 11;\n _context.t0 = _context[\"catch\"](0);\n console.error('Error extracting URL title:', _context.t0);\n return _context.abrupt(\"return\", {\n url: url,\n title: null,\n error: _context.t0.message\n });\n case 15:\n case \"end\":\n return _context.stop();\n }\n }, _callee, null, [[0, 11]]);\n }));\n return function extractUrlTitle(_x) {\n return _ref.apply(this, arguments);\n };\n}();\n\n/**\n * Extract a URL and its title from arbitrary text\n * @param text The text that might contain a URL\n * @returns Promise resolving to the URL and title if found\n */\nvar extractTitleFromText = /*#__PURE__*/function () {\n var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(text) {\n var response, result;\n return _regeneratorRuntime().wrap(function _callee2$(_context2) {\n while (1) switch (_context2.prev = _context2.next) {\n case 0:\n _context2.prev = 0;\n _context2.next = 3;\n return fetch('/api/url/extract-from-text', {\n method: 'POST',\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json'\n },\n body: JSON.stringify({\n text: text\n })\n });\n case 3:\n response = _context2.sent;\n _context2.next = 6;\n return (0,_authUtils__WEBPACK_IMPORTED_MODULE_0__.handleAuthResponse)(response, 'Failed to extract title from text');\n case 6:\n _context2.next = 8;\n return response.json();\n case 8:\n result = _context2.sent;\n if (!(result.found === false)) {\n _context2.next = 11;\n break;\n }\n return _context2.abrupt(\"return\", null);\n case 11:\n return _context2.abrupt(\"return\", result);\n case 14:\n _context2.prev = 14;\n _context2.t0 = _context2[\"catch\"](0);\n console.error('Error extracting title from text:', _context2.t0);\n return _context2.abrupt(\"return\", null);\n case 18:\n case \"end\":\n return _context2.stop();\n }\n }, _callee2, null, [[0, 14]]);\n }));\n return function extractTitleFromText(_x2) {\n return _ref2.apply(this, arguments);\n };\n}();\n\n/**\n * Check if a string is likely a URL\n * @param text The text to check\n * @returns True if the text appears to be a URL\n */\nvar isUrl = function isUrl(text) {\n // Basic URL validation regex\n var urlRegex = /^(https?:\\/\\/)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$/i;\n return urlRegex.test(text.trim());\n};\n\nconst $ReactRefreshModuleId$ = __webpack_require__.$Refresh$.moduleId;\nconst $ReactRefreshCurrentExports$ = __react_refresh_utils__.getModuleExports(\n\t$ReactRefreshModuleId$\n);\n\nfunction $ReactRefreshModuleRuntime$(exports) {\n\tif (true) {\n\t\tlet errorOverlay;\n\t\tif (typeof __react_refresh_error_overlay__ !== 'undefined') {\n\t\t\terrorOverlay = __react_refresh_error_overlay__;\n\t\t}\n\t\tlet testMode;\n\t\tif (typeof __react_refresh_test__ !== 'undefined') {\n\t\t\ttestMode = __react_refresh_test__;\n\t\t}\n\t\treturn __react_refresh_utils__.executeRuntime(\n\t\t\texports,\n\t\t\t$ReactRefreshModuleId$,\n\t\t\tmodule.hot,\n\t\t\terrorOverlay,\n\t\t\ttestMode\n\t\t);\n\t}\n}\n\nif (typeof Promise !== 'undefined' && $ReactRefreshCurrentExports$ instanceof Promise) {\n\t$ReactRefreshCurrentExports$.then($ReactRefreshModuleRuntime$);\n} else {\n\t$ReactRefreshModuleRuntime$($ReactRefreshCurrentExports$);\n}\n\n//# sourceURL=webpack://tududi/./frontend/utils/urlService.ts?"); - -/***/ }), - -/***/ "./node_modules/css-loader/dist/cjs.js!./node_modules/postcss-loader/dist/cjs.js!./frontend/styles/tailwind.css": -/*!**********************************************************************************************************************!*\ - !*** ./node_modules/css-loader/dist/cjs.js!./node_modules/postcss-loader/dist/cjs.js!./frontend/styles/tailwind.css ***! - \**********************************************************************************************************************/ -/***/ ((module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `*, ::before, ::after {\n --tw-border-spacing-x: 0;\n --tw-border-spacing-y: 0;\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-rotate: 0;\n --tw-skew-x: 0;\n --tw-skew-y: 0;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-pan-x: ;\n --tw-pan-y: ;\n --tw-pinch-zoom: ;\n --tw-scroll-snap-strictness: proximity;\n --tw-gradient-from-position: ;\n --tw-gradient-via-position: ;\n --tw-gradient-to-position: ;\n --tw-ordinal: ;\n --tw-slashed-zero: ;\n --tw-numeric-figure: ;\n --tw-numeric-spacing: ;\n --tw-numeric-fraction: ;\n --tw-ring-inset: ;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-color: rgb(59 130 246 / 0.5);\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-ring-shadow: 0 0 #0000;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-colored: 0 0 #0000;\n --tw-blur: ;\n --tw-brightness: ;\n --tw-contrast: ;\n --tw-grayscale: ;\n --tw-hue-rotate: ;\n --tw-invert: ;\n --tw-saturate: ;\n --tw-sepia: ;\n --tw-drop-shadow: ;\n --tw-backdrop-blur: ;\n --tw-backdrop-brightness: ;\n --tw-backdrop-contrast: ;\n --tw-backdrop-grayscale: ;\n --tw-backdrop-hue-rotate: ;\n --tw-backdrop-invert: ;\n --tw-backdrop-opacity: ;\n --tw-backdrop-saturate: ;\n --tw-backdrop-sepia: ;\n --tw-contain-size: ;\n --tw-contain-layout: ;\n --tw-contain-paint: ;\n --tw-contain-style: ;\n}\n\n::backdrop {\n --tw-border-spacing-x: 0;\n --tw-border-spacing-y: 0;\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-rotate: 0;\n --tw-skew-x: 0;\n --tw-skew-y: 0;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n --tw-pan-x: ;\n --tw-pan-y: ;\n --tw-pinch-zoom: ;\n --tw-scroll-snap-strictness: proximity;\n --tw-gradient-from-position: ;\n --tw-gradient-via-position: ;\n --tw-gradient-to-position: ;\n --tw-ordinal: ;\n --tw-slashed-zero: ;\n --tw-numeric-figure: ;\n --tw-numeric-spacing: ;\n --tw-numeric-fraction: ;\n --tw-ring-inset: ;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-color: rgb(59 130 246 / 0.5);\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-ring-shadow: 0 0 #0000;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-colored: 0 0 #0000;\n --tw-blur: ;\n --tw-brightness: ;\n --tw-contrast: ;\n --tw-grayscale: ;\n --tw-hue-rotate: ;\n --tw-invert: ;\n --tw-saturate: ;\n --tw-sepia: ;\n --tw-drop-shadow: ;\n --tw-backdrop-blur: ;\n --tw-backdrop-brightness: ;\n --tw-backdrop-contrast: ;\n --tw-backdrop-grayscale: ;\n --tw-backdrop-hue-rotate: ;\n --tw-backdrop-invert: ;\n --tw-backdrop-opacity: ;\n --tw-backdrop-saturate: ;\n --tw-backdrop-sepia: ;\n --tw-contain-size: ;\n --tw-contain-layout: ;\n --tw-contain-paint: ;\n --tw-contain-style: ;\n}/*\n! tailwindcss v3.4.13 | MIT License | https://tailwindcss.com\n*//*\n1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)\n2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)\n*/\n\n*,\n::before,\n::after {\n box-sizing: border-box; /* 1 */\n border-width: 0; /* 2 */\n border-style: solid; /* 2 */\n border-color: #e5e7eb; /* 2 */\n}\n\n::before,\n::after {\n --tw-content: '';\n}\n\n/*\n1. Use a consistent sensible line-height in all browsers.\n2. Prevent adjustments of font size after orientation changes in iOS.\n3. Use a more readable tab size.\n4. Use the user's configured \\`sans\\` font-family by default.\n5. Use the user's configured \\`sans\\` font-feature-settings by default.\n6. Use the user's configured \\`sans\\` font-variation-settings by default.\n7. Disable tap highlights on iOS\n*/\n\nhtml,\n:host {\n line-height: 1.5; /* 1 */\n -webkit-text-size-adjust: 100%; /* 2 */\n -moz-tab-size: 4; /* 3 */\n -o-tab-size: 4;\n tab-size: 4; /* 3 */\n font-family: ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\"; /* 4 */\n font-feature-settings: normal; /* 5 */\n font-variation-settings: normal; /* 6 */\n -webkit-tap-highlight-color: transparent; /* 7 */\n}\n\n/*\n1. Remove the margin in all browsers.\n2. Inherit line-height from \\`html\\` so users can set them as a class directly on the \\`html\\` element.\n*/\n\nbody {\n margin: 0; /* 1 */\n line-height: inherit; /* 2 */\n}\n\n/*\n1. Add the correct height in Firefox.\n2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)\n3. Ensure horizontal rules are visible by default.\n*/\n\nhr {\n height: 0; /* 1 */\n color: inherit; /* 2 */\n border-top-width: 1px; /* 3 */\n}\n\n/*\nAdd the correct text decoration in Chrome, Edge, and Safari.\n*/\n\nabbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n}\n\n/*\nRemove the default font size and weight for headings.\n*/\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n font-size: inherit;\n font-weight: inherit;\n}\n\n/*\nReset links to optimize for opt-in styling instead of opt-out.\n*/\n\na {\n color: inherit;\n text-decoration: inherit;\n}\n\n/*\nAdd the correct font weight in Edge and Safari.\n*/\n\nb,\nstrong {\n font-weight: bolder;\n}\n\n/*\n1. Use the user's configured \\`mono\\` font-family by default.\n2. Use the user's configured \\`mono\\` font-feature-settings by default.\n3. Use the user's configured \\`mono\\` font-variation-settings by default.\n4. Correct the odd \\`em\\` font sizing in all browsers.\n*/\n\ncode,\nkbd,\nsamp,\npre {\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace; /* 1 */\n font-feature-settings: normal; /* 2 */\n font-variation-settings: normal; /* 3 */\n font-size: 1em; /* 4 */\n}\n\n/*\nAdd the correct font size in all browsers.\n*/\n\nsmall {\n font-size: 80%;\n}\n\n/*\nPrevent \\`sub\\` and \\`sup\\` elements from affecting the line height in all browsers.\n*/\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\n/*\n1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)\n2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)\n3. Remove gaps between table borders by default.\n*/\n\ntable {\n text-indent: 0; /* 1 */\n border-color: inherit; /* 2 */\n border-collapse: collapse; /* 3 */\n}\n\n/*\n1. Change the font styles in all browsers.\n2. Remove the margin in Firefox and Safari.\n3. Remove default padding in all browsers.\n*/\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n font-family: inherit; /* 1 */\n font-feature-settings: inherit; /* 1 */\n font-variation-settings: inherit; /* 1 */\n font-size: 100%; /* 1 */\n font-weight: inherit; /* 1 */\n line-height: inherit; /* 1 */\n letter-spacing: inherit; /* 1 */\n color: inherit; /* 1 */\n margin: 0; /* 2 */\n padding: 0; /* 3 */\n}\n\n/*\nRemove the inheritance of text transform in Edge and Firefox.\n*/\n\nbutton,\nselect {\n text-transform: none;\n}\n\n/*\n1. Correct the inability to style clickable types in iOS and Safari.\n2. Remove default button styles.\n*/\n\nbutton,\ninput:where([type='button']),\ninput:where([type='reset']),\ninput:where([type='submit']) {\n -webkit-appearance: button; /* 1 */\n background-color: transparent; /* 2 */\n background-image: none; /* 2 */\n}\n\n/*\nUse the modern Firefox focus style for all focusable elements.\n*/\n\n:-moz-focusring {\n outline: auto;\n}\n\n/*\nRemove the additional \\`:invalid\\` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)\n*/\n\n:-moz-ui-invalid {\n box-shadow: none;\n}\n\n/*\nAdd the correct vertical alignment in Chrome and Firefox.\n*/\n\nprogress {\n vertical-align: baseline;\n}\n\n/*\nCorrect the cursor style of increment and decrement buttons in Safari.\n*/\n\n::-webkit-inner-spin-button,\n::-webkit-outer-spin-button {\n height: auto;\n}\n\n/*\n1. Correct the odd appearance in Chrome and Safari.\n2. Correct the outline style in Safari.\n*/\n\n[type='search'] {\n -webkit-appearance: textfield; /* 1 */\n outline-offset: -2px; /* 2 */\n}\n\n/*\nRemove the inner padding in Chrome and Safari on macOS.\n*/\n\n::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/*\n1. Correct the inability to style clickable types in iOS and Safari.\n2. Change font properties to \\`inherit\\` in Safari.\n*/\n\n::-webkit-file-upload-button {\n -webkit-appearance: button; /* 1 */\n font: inherit; /* 2 */\n}\n\n/*\nAdd the correct display in Chrome and Safari.\n*/\n\nsummary {\n display: list-item;\n}\n\n/*\nRemoves the default spacing and border for appropriate elements.\n*/\n\nblockquote,\ndl,\ndd,\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\nhr,\nfigure,\np,\npre {\n margin: 0;\n}\n\nfieldset {\n margin: 0;\n padding: 0;\n}\n\nlegend {\n padding: 0;\n}\n\nol,\nul,\nmenu {\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n/*\nReset default styling for dialogs.\n*/\ndialog {\n padding: 0;\n}\n\n/*\nPrevent resizing textareas horizontally by default.\n*/\n\ntextarea {\n resize: vertical;\n}\n\n/*\n1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)\n2. Set the default placeholder color to the user's configured gray 400 color.\n*/\n\ninput::-moz-placeholder, textarea::-moz-placeholder {\n opacity: 1; /* 1 */\n color: #9ca3af; /* 2 */\n}\n\ninput::placeholder,\ntextarea::placeholder {\n opacity: 1; /* 1 */\n color: #9ca3af; /* 2 */\n}\n\n/*\nSet the default cursor for buttons.\n*/\n\nbutton,\n[role=\"button\"] {\n cursor: pointer;\n}\n\n/*\nMake sure disabled buttons don't get the pointer cursor.\n*/\n:disabled {\n cursor: default;\n}\n\n/*\n1. Make replaced elements \\`display: block\\` by default. (https://github.com/mozdevs/cssremedy/issues/14)\n2. Add \\`vertical-align: middle\\` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)\n This can trigger a poorly considered lint error in some tools but is included by design.\n*/\n\nimg,\nsvg,\nvideo,\ncanvas,\naudio,\niframe,\nembed,\nobject {\n display: block; /* 1 */\n vertical-align: middle; /* 2 */\n}\n\n/*\nConstrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)\n*/\n\nimg,\nvideo {\n max-width: 100%;\n height: auto;\n}\n\n/* Make elements with the HTML hidden attribute stay hidden by default */\n[hidden] {\n display: none;\n}\n.container {\n width: 100%;\n}\n@media (min-width: 640px) {\n\n .container {\n max-width: 640px;\n }\n}\n@media (min-width: 768px) {\n\n .container {\n max-width: 768px;\n }\n}\n@media (min-width: 1024px) {\n\n .container {\n max-width: 1024px;\n }\n}\n@media (min-width: 1280px) {\n\n .container {\n max-width: 1280px;\n }\n}\n@media (min-width: 1536px) {\n\n .container {\n max-width: 1536px;\n }\n}\n.visible {\n visibility: visible;\n}\n.fixed {\n position: fixed;\n}\n.absolute {\n position: absolute;\n}\n.relative {\n position: relative;\n}\n.inset-0 {\n inset: 0px;\n}\n.bottom-0 {\n bottom: 0px;\n}\n.bottom-4 {\n bottom: 1rem;\n}\n.bottom-6 {\n bottom: 1.5rem;\n}\n.left-0 {\n left: 0px;\n}\n.left-2 {\n left: 0.5rem;\n}\n.right-0 {\n right: 0px;\n}\n.right-4 {\n right: 1rem;\n}\n.right-6 {\n right: 1.5rem;\n}\n.top-0 {\n top: 0px;\n}\n.top-16 {\n top: 4rem;\n}\n.top-2 {\n top: 0.5rem;\n}\n.z-10 {\n z-index: 10;\n}\n.z-40 {\n z-index: 40;\n}\n.z-50 {\n z-index: 50;\n}\n.col-span-full {\n grid-column: 1 / -1;\n}\n.m-1 {\n margin: 0.25rem;\n}\n.mx-4 {\n margin-left: 1rem;\n margin-right: 1rem;\n}\n.mx-auto {\n margin-left: auto;\n margin-right: auto;\n}\n.mb-1 {\n margin-bottom: 0.25rem;\n}\n.mb-2 {\n margin-bottom: 0.5rem;\n}\n.mb-3 {\n margin-bottom: 0.75rem;\n}\n.mb-4 {\n margin-bottom: 1rem;\n}\n.mb-6 {\n margin-bottom: 1.5rem;\n}\n.mb-8 {\n margin-bottom: 2rem;\n}\n.ml-0 {\n margin-left: 0px;\n}\n.ml-1 {\n margin-left: 0.25rem;\n}\n.ml-2 {\n margin-left: 0.5rem;\n}\n.ml-3 {\n margin-left: 0.75rem;\n}\n.ml-4 {\n margin-left: 1rem;\n}\n.ml-72 {\n margin-left: 18rem;\n}\n.mr-2 {\n margin-right: 0.5rem;\n}\n.mr-3 {\n margin-right: 0.75rem;\n}\n.mr-4 {\n margin-right: 1rem;\n}\n.mt-1 {\n margin-top: 0.25rem;\n}\n.mt-2 {\n margin-top: 0.5rem;\n}\n.mt-4 {\n margin-top: 1rem;\n}\n.mt-6 {\n margin-top: 1.5rem;\n}\n.mt-auto {\n margin-top: auto;\n}\n.line-clamp-2 {\n overflow: hidden;\n display: -webkit-box;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: 2;\n}\n.block {\n display: block;\n}\n.inline-block {\n display: inline-block;\n}\n.inline {\n display: inline;\n}\n.flex {\n display: flex;\n}\n.inline-flex {\n display: inline-flex;\n}\n.grid {\n display: grid;\n}\n.hidden {\n display: none;\n}\n.h-16 {\n height: 4rem;\n}\n.h-2 {\n height: 0.5rem;\n}\n.h-3 {\n height: 0.75rem;\n}\n.h-4 {\n height: 1rem;\n}\n.h-5 {\n height: 1.25rem;\n}\n.h-6 {\n height: 1.5rem;\n}\n.h-64 {\n height: 16rem;\n}\n.h-8 {\n height: 2rem;\n}\n.h-\\\\[calc\\\\(100vh-4rem\\\\)\\\\] {\n height: calc(100vh - 4rem);\n}\n.h-full {\n height: 100%;\n}\n.h-screen {\n height: 100vh;\n}\n.max-h-60 {\n max-height: 15rem;\n}\n.min-h-\\\\[40px\\\\] {\n min-height: 40px;\n}\n.min-h-screen {\n min-height: 100vh;\n}\n.w-0 {\n width: 0px;\n}\n.w-12 {\n width: 3rem;\n}\n.w-16 {\n width: 4rem;\n}\n.w-28 {\n width: 7rem;\n}\n.w-3 {\n width: 0.75rem;\n}\n.w-4 {\n width: 1rem;\n}\n.w-40 {\n width: 10rem;\n}\n.w-48 {\n width: 12rem;\n}\n.w-5 {\n width: 1.25rem;\n}\n.w-6 {\n width: 1.5rem;\n}\n.w-8 {\n width: 2rem;\n}\n.w-full {\n width: 100%;\n}\n.w-screen {\n width: 100vw;\n}\n.max-w-5xl {\n max-width: 64rem;\n}\n.max-w-6xl {\n max-width: 72rem;\n}\n.max-w-full {\n max-width: 100%;\n}\n.max-w-lg {\n max-width: 32rem;\n}\n.max-w-sm {\n max-width: 24rem;\n}\n.flex-1 {\n flex: 1 1 0%;\n}\n.flex-shrink-0 {\n flex-shrink: 0;\n}\n.flex-grow {\n flex-grow: 1;\n}\n.origin-top-right {\n transform-origin: top right;\n}\n.translate-x-0 {\n --tw-translate-x: 0px;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.translate-x-6 {\n --tw-translate-x: 1.5rem;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.rotate-0 {\n --tw-rotate: 0deg;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.rotate-180 {\n --tw-rotate: 180deg;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.scale-100 {\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.scale-95 {\n --tw-scale-x: .95;\n --tw-scale-y: .95;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.transform {\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n@keyframes pulse {\n\n 50% {\n opacity: .5;\n }\n}\n.animate-pulse {\n animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n}\n.cursor-not-allowed {\n cursor: not-allowed;\n}\n.cursor-pointer {\n cursor: pointer;\n}\n.resize {\n resize: both;\n}\n.appearance-none {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n}\n.grid-cols-1 {\n grid-template-columns: repeat(1, minmax(0, 1fr));\n}\n.grid-cols-2 {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n}\n.flex-row {\n flex-direction: row;\n}\n.flex-col {\n flex-direction: column;\n}\n.flex-wrap {\n flex-wrap: wrap;\n}\n.items-start {\n align-items: flex-start;\n}\n.items-center {\n align-items: center;\n}\n.justify-start {\n justify-content: flex-start;\n}\n.justify-end {\n justify-content: flex-end;\n}\n.justify-center {\n justify-content: center;\n}\n.justify-between {\n justify-content: space-between;\n}\n.gap-2 {\n gap: 0.5rem;\n}\n.gap-4 {\n gap: 1rem;\n}\n.space-x-0 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-x-reverse: 0;\n margin-right: calc(0px * var(--tw-space-x-reverse));\n margin-left: calc(0px * calc(1 - var(--tw-space-x-reverse)));\n}\n.space-x-1 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-x-reverse: 0;\n margin-right: calc(0.25rem * var(--tw-space-x-reverse));\n margin-left: calc(0.25rem * calc(1 - var(--tw-space-x-reverse)));\n}\n.space-x-2 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-x-reverse: 0;\n margin-right: calc(0.5rem * var(--tw-space-x-reverse));\n margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));\n}\n.space-x-4 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-x-reverse: 0;\n margin-right: calc(1rem * var(--tw-space-x-reverse));\n margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));\n}\n.space-y-1 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));\n}\n.space-y-2 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));\n}\n.space-y-3 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.75rem * var(--tw-space-y-reverse));\n}\n.space-y-4 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(1rem * var(--tw-space-y-reverse));\n}\n.overflow-auto {\n overflow: auto;\n}\n.overflow-hidden {\n overflow: hidden;\n}\n.overflow-y-auto {\n overflow-y: auto;\n}\n.truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.whitespace-pre-line {\n white-space: pre-line;\n}\n.break-words {\n overflow-wrap: break-word;\n}\n.rounded {\n border-radius: 0.25rem;\n}\n.rounded-full {\n border-radius: 9999px;\n}\n.rounded-lg {\n border-radius: 0.5rem;\n}\n.rounded-md {\n border-radius: 0.375rem;\n}\n.rounded-t-lg {\n border-top-left-radius: 0.5rem;\n border-top-right-radius: 0.5rem;\n}\n.border {\n border-width: 1px;\n}\n.border-2 {\n border-width: 2px;\n}\n.border-b {\n border-bottom-width: 1px;\n}\n.border-b-2 {\n border-bottom-width: 2px;\n}\n.border-l-4 {\n border-left-width: 4px;\n}\n.border-t {\n border-top-width: 1px;\n}\n.border-none {\n border-style: none;\n}\n.border-blue-200 {\n --tw-border-opacity: 1;\n border-color: rgb(191 219 254 / var(--tw-border-opacity));\n}\n.border-blue-500 {\n --tw-border-opacity: 1;\n border-color: rgb(59 130 246 / var(--tw-border-opacity));\n}\n.border-blue-700 {\n --tw-border-opacity: 1;\n border-color: rgb(29 78 216 / var(--tw-border-opacity));\n}\n.border-gray-200 {\n --tw-border-opacity: 1;\n border-color: rgb(229 231 235 / var(--tw-border-opacity));\n}\n.border-gray-300 {\n --tw-border-opacity: 1;\n border-color: rgb(209 213 219 / var(--tw-border-opacity));\n}\n.border-green-200 {\n --tw-border-opacity: 1;\n border-color: rgb(187 247 208 / var(--tw-border-opacity));\n}\n.border-green-500 {\n --tw-border-opacity: 1;\n border-color: rgb(34 197 94 / var(--tw-border-opacity));\n}\n.border-red-200 {\n --tw-border-opacity: 1;\n border-color: rgb(254 202 202 / var(--tw-border-opacity));\n}\n.border-red-700 {\n --tw-border-opacity: 1;\n border-color: rgb(185 28 28 / var(--tw-border-opacity));\n}\n.border-white {\n --tw-border-opacity: 1;\n border-color: rgb(255 255 255 / var(--tw-border-opacity));\n}\n.bg-black {\n --tw-bg-opacity: 1;\n background-color: rgb(0 0 0 / var(--tw-bg-opacity));\n}\n.bg-blue-100 {\n --tw-bg-opacity: 1;\n background-color: rgb(219 234 254 / var(--tw-bg-opacity));\n}\n.bg-blue-400 {\n --tw-bg-opacity: 1;\n background-color: rgb(96 165 250 / var(--tw-bg-opacity));\n}\n.bg-blue-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(239 246 255 / var(--tw-bg-opacity));\n}\n.bg-blue-500 {\n --tw-bg-opacity: 1;\n background-color: rgb(59 130 246 / var(--tw-bg-opacity));\n}\n.bg-blue-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(37 99 235 / var(--tw-bg-opacity));\n}\n.bg-gray-100 {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity));\n}\n.bg-gray-200 {\n --tw-bg-opacity: 1;\n background-color: rgb(229 231 235 / var(--tw-bg-opacity));\n}\n.bg-gray-300 {\n --tw-bg-opacity: 1;\n background-color: rgb(209 213 219 / var(--tw-bg-opacity));\n}\n.bg-gray-400 {\n --tw-bg-opacity: 1;\n background-color: rgb(156 163 175 / var(--tw-bg-opacity));\n}\n.bg-gray-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(249 250 251 / var(--tw-bg-opacity));\n}\n.bg-gray-500 {\n --tw-bg-opacity: 1;\n background-color: rgb(107 114 128 / var(--tw-bg-opacity));\n}\n.bg-gray-900 {\n --tw-bg-opacity: 1;\n background-color: rgb(17 24 39 / var(--tw-bg-opacity));\n}\n.bg-green-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(240 253 244 / var(--tw-bg-opacity));\n}\n.bg-green-500 {\n --tw-bg-opacity: 1;\n background-color: rgb(34 197 94 / var(--tw-bg-opacity));\n}\n.bg-green-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(22 163 74 / var(--tw-bg-opacity));\n}\n.bg-purple-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(147 51 234 / var(--tw-bg-opacity));\n}\n.bg-red-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(254 242 242 / var(--tw-bg-opacity));\n}\n.bg-red-500 {\n --tw-bg-opacity: 1;\n background-color: rgb(239 68 68 / var(--tw-bg-opacity));\n}\n.bg-red-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(220 38 38 / var(--tw-bg-opacity));\n}\n.bg-transparent {\n background-color: transparent;\n}\n.bg-white {\n --tw-bg-opacity: 1;\n background-color: rgb(255 255 255 / var(--tw-bg-opacity));\n}\n.bg-yellow-500 {\n --tw-bg-opacity: 1;\n background-color: rgb(234 179 8 / var(--tw-bg-opacity));\n}\n.bg-opacity-50 {\n --tw-bg-opacity: 0.5;\n}\n.bg-opacity-80 {\n --tw-bg-opacity: 0.8;\n}\n.object-cover {\n -o-object-fit: cover;\n object-fit: cover;\n}\n.p-1 {\n padding: 0.25rem;\n}\n.p-2 {\n padding: 0.5rem;\n}\n.p-3 {\n padding: 0.75rem;\n}\n.p-4 {\n padding: 1rem;\n}\n.p-6 {\n padding: 1.5rem;\n}\n.p-8 {\n padding: 2rem;\n}\n.px-2 {\n padding-left: 0.5rem;\n padding-right: 0.5rem;\n}\n.px-2\\\\.5 {\n padding-left: 0.625rem;\n padding-right: 0.625rem;\n}\n.px-3 {\n padding-left: 0.75rem;\n padding-right: 0.75rem;\n}\n.px-4 {\n padding-left: 1rem;\n padding-right: 1rem;\n}\n.px-8 {\n padding-left: 2rem;\n padding-right: 2rem;\n}\n.py-0\\\\.5 {\n padding-top: 0.125rem;\n padding-bottom: 0.125rem;\n}\n.py-1 {\n padding-top: 0.25rem;\n padding-bottom: 0.25rem;\n}\n.py-1\\\\.5 {\n padding-top: 0.375rem;\n padding-bottom: 0.375rem;\n}\n.py-2 {\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n}\n.py-3 {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n}\n.py-4 {\n padding-top: 1rem;\n padding-bottom: 1rem;\n}\n.py-6 {\n padding-top: 1.5rem;\n padding-bottom: 1.5rem;\n}\n.pb-3 {\n padding-bottom: 0.75rem;\n}\n.pr-4 {\n padding-right: 1rem;\n}\n.pt-24 {\n padding-top: 6rem;\n}\n.pt-3 {\n padding-top: 0.75rem;\n}\n.pt-8 {\n padding-top: 2rem;\n}\n.text-left {\n text-align: left;\n}\n.text-center {\n text-align: center;\n}\n.text-2xl {\n font-size: 1.5rem;\n line-height: 2rem;\n}\n.text-5xl {\n font-size: 3rem;\n line-height: 1;\n}\n.text-base {\n font-size: 1rem;\n line-height: 1.5rem;\n}\n.text-lg {\n font-size: 1.125rem;\n line-height: 1.75rem;\n}\n.text-sm {\n font-size: 0.875rem;\n line-height: 1.25rem;\n}\n.text-xl {\n font-size: 1.25rem;\n line-height: 1.75rem;\n}\n.text-xs {\n font-size: 0.75rem;\n line-height: 1rem;\n}\n.font-bold {\n font-weight: 700;\n}\n.font-extrabold {\n font-weight: 800;\n}\n.font-light {\n font-weight: 300;\n}\n.font-medium {\n font-weight: 500;\n}\n.font-semibold {\n font-weight: 600;\n}\n.uppercase {\n text-transform: uppercase;\n}\n.capitalize {\n text-transform: capitalize;\n}\n.tracking-wider {\n letter-spacing: 0.05em;\n}\n.text-black {\n --tw-text-opacity: 1;\n color: rgb(0 0 0 / var(--tw-text-opacity));\n}\n.text-blue-400 {\n --tw-text-opacity: 1;\n color: rgb(96 165 250 / var(--tw-text-opacity));\n}\n.text-blue-500 {\n --tw-text-opacity: 1;\n color: rgb(59 130 246 / var(--tw-text-opacity));\n}\n.text-blue-600 {\n --tw-text-opacity: 1;\n color: rgb(37 99 235 / var(--tw-text-opacity));\n}\n.text-blue-800 {\n --tw-text-opacity: 1;\n color: rgb(30 64 175 / var(--tw-text-opacity));\n}\n.text-gray-300 {\n --tw-text-opacity: 1;\n color: rgb(209 213 219 / var(--tw-text-opacity));\n}\n.text-gray-400 {\n --tw-text-opacity: 1;\n color: rgb(156 163 175 / var(--tw-text-opacity));\n}\n.text-gray-500 {\n --tw-text-opacity: 1;\n color: rgb(107 114 128 / var(--tw-text-opacity));\n}\n.text-gray-600 {\n --tw-text-opacity: 1;\n color: rgb(75 85 99 / var(--tw-text-opacity));\n}\n.text-gray-700 {\n --tw-text-opacity: 1;\n color: rgb(55 65 81 / var(--tw-text-opacity));\n}\n.text-gray-800 {\n --tw-text-opacity: 1;\n color: rgb(31 41 55 / var(--tw-text-opacity));\n}\n.text-gray-900 {\n --tw-text-opacity: 1;\n color: rgb(17 24 39 / var(--tw-text-opacity));\n}\n.text-green-400 {\n --tw-text-opacity: 1;\n color: rgb(74 222 128 / var(--tw-text-opacity));\n}\n.text-green-500 {\n --tw-text-opacity: 1;\n color: rgb(34 197 94 / var(--tw-text-opacity));\n}\n.text-green-800 {\n --tw-text-opacity: 1;\n color: rgb(22 101 52 / var(--tw-text-opacity));\n}\n.text-red-500 {\n --tw-text-opacity: 1;\n color: rgb(239 68 68 / var(--tw-text-opacity));\n}\n.text-red-600 {\n --tw-text-opacity: 1;\n color: rgb(220 38 38 / var(--tw-text-opacity));\n}\n.text-red-800 {\n --tw-text-opacity: 1;\n color: rgb(153 27 27 / var(--tw-text-opacity));\n}\n.text-white {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity));\n}\n.text-yellow-500 {\n --tw-text-opacity: 1;\n color: rgb(234 179 8 / var(--tw-text-opacity));\n}\n.no-underline {\n text-decoration-line: none;\n}\n.placeholder-gray-400::-moz-placeholder {\n --tw-placeholder-opacity: 1;\n color: rgb(156 163 175 / var(--tw-placeholder-opacity));\n}\n.placeholder-gray-400::placeholder {\n --tw-placeholder-opacity: 1;\n color: rgb(156 163 175 / var(--tw-placeholder-opacity));\n}\n.opacity-0 {\n opacity: 0;\n}\n.opacity-100 {\n opacity: 1;\n}\n.opacity-20 {\n opacity: 0.2;\n}\n.opacity-50 {\n opacity: 0.5;\n}\n.shadow {\n --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-lg {\n --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-md {\n --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-sm {\n --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-xl {\n --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.outline-none {\n outline: 2px solid transparent;\n outline-offset: 2px;\n}\n.ring-1 {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);\n}\n.ring-black {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity));\n}\n.ring-opacity-5 {\n --tw-ring-opacity: 0.05;\n}\n.filter {\n filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);\n}\n.transition {\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-all {\n transition-property: all;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-colors {\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-opacity {\n transition-property: opacity;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-transform {\n transition-property: transform;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.duration-150 {\n transition-duration: 150ms;\n}\n.duration-200 {\n transition-duration: 200ms;\n}\n.duration-300 {\n transition-duration: 300ms;\n}\n.ease-in-out {\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.spinner {\n border: 4px solid rgba(0, 0, 0, 0.1);\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border-left-color: #09f;\n animation: spin 1s ease infinite;\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n\ninput:focus, select:focus, textarea:focus {\n outline: none;\n box-shadow: none;\n}\n\n.hover\\\\:scale-110:hover {\n --tw-scale-x: 1.1;\n --tw-scale-y: 1.1;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n\n.hover\\\\:bg-blue-100:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(219 234 254 / var(--tw-bg-opacity));\n}\n\n.hover\\\\:bg-blue-600:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(37 99 235 / var(--tw-bg-opacity));\n}\n\n.hover\\\\:bg-blue-700:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(29 78 216 / var(--tw-bg-opacity));\n}\n\n.hover\\\\:bg-gray-100:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity));\n}\n\n.hover\\\\:bg-gray-200:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(229 231 235 / var(--tw-bg-opacity));\n}\n\n.hover\\\\:bg-gray-300:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(209 213 219 / var(--tw-bg-opacity));\n}\n\n.hover\\\\:bg-gray-400:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(156 163 175 / var(--tw-bg-opacity));\n}\n\n.hover\\\\:bg-gray-50:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(249 250 251 / var(--tw-bg-opacity));\n}\n\n.hover\\\\:bg-green-700:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(21 128 61 / var(--tw-bg-opacity));\n}\n\n.hover\\\\:bg-purple-700:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(126 34 206 / var(--tw-bg-opacity));\n}\n\n.hover\\\\:bg-red-100:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(254 226 226 / var(--tw-bg-opacity));\n}\n\n.hover\\\\:bg-red-600:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(220 38 38 / var(--tw-bg-opacity));\n}\n\n.hover\\\\:bg-red-700:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(185 28 28 / var(--tw-bg-opacity));\n}\n\n.hover\\\\:text-black:hover {\n --tw-text-opacity: 1;\n color: rgb(0 0 0 / var(--tw-text-opacity));\n}\n\n.hover\\\\:text-blue-700:hover {\n --tw-text-opacity: 1;\n color: rgb(29 78 216 / var(--tw-text-opacity));\n}\n\n.hover\\\\:text-gray-700:hover {\n --tw-text-opacity: 1;\n color: rgb(55 65 81 / var(--tw-text-opacity));\n}\n\n.hover\\\\:text-gray-800:hover {\n --tw-text-opacity: 1;\n color: rgb(31 41 55 / var(--tw-text-opacity));\n}\n\n.hover\\\\:text-red-500:hover {\n --tw-text-opacity: 1;\n color: rgb(239 68 68 / var(--tw-text-opacity));\n}\n\n.hover\\\\:text-red-700:hover {\n --tw-text-opacity: 1;\n color: rgb(185 28 28 / var(--tw-text-opacity));\n}\n\n.hover\\\\:underline:hover {\n text-decoration-line: underline;\n}\n\n.focus\\\\:outline-none:focus {\n outline: 2px solid transparent;\n outline-offset: 2px;\n}\n\n.focus\\\\:ring-0:focus {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);\n}\n\n.focus\\\\:ring-2:focus {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);\n}\n\n.focus\\\\:ring-blue-500:focus {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity));\n}\n\n.dark\\\\:border-blue-800:is(.dark *) {\n --tw-border-opacity: 1;\n border-color: rgb(30 64 175 / var(--tw-border-opacity));\n}\n\n.dark\\\\:border-gray-700:is(.dark *) {\n --tw-border-opacity: 1;\n border-color: rgb(55 65 81 / var(--tw-border-opacity));\n}\n\n.dark\\\\:border-gray-800:is(.dark *) {\n --tw-border-opacity: 1;\n border-color: rgb(31 41 55 / var(--tw-border-opacity));\n}\n\n.dark\\\\:border-gray-900:is(.dark *) {\n --tw-border-opacity: 1;\n border-color: rgb(17 24 39 / var(--tw-border-opacity));\n}\n\n.dark\\\\:border-green-800:is(.dark *) {\n --tw-border-opacity: 1;\n border-color: rgb(22 101 52 / var(--tw-border-opacity));\n}\n\n.dark\\\\:border-red-800:is(.dark *) {\n --tw-border-opacity: 1;\n border-color: rgb(153 27 27 / var(--tw-border-opacity));\n}\n\n.dark\\\\:bg-blue-500:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(59 130 246 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:bg-blue-700:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(29 78 216 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:bg-blue-900:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(30 58 138 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:bg-gray-600:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(75 85 99 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:bg-gray-700:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(55 65 81 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:bg-gray-800:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(31 41 55 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:bg-gray-900:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(17 24 39 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:bg-green-700:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(21 128 61 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:bg-green-900:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(20 83 45 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:bg-purple-700:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(126 34 206 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:bg-red-500:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(239 68 68 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:bg-red-700:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(185 28 28 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:bg-red-900:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(127 29 29 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:bg-transparent:is(.dark *) {\n background-color: transparent;\n}\n\n.dark\\\\:text-blue-100:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(219 234 254 / var(--tw-text-opacity));\n}\n\n.dark\\\\:text-blue-200:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(191 219 254 / var(--tw-text-opacity));\n}\n\n.dark\\\\:text-blue-400:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(96 165 250 / var(--tw-text-opacity));\n}\n\n.dark\\\\:text-gray-100:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(243 244 246 / var(--tw-text-opacity));\n}\n\n.dark\\\\:text-gray-200:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(229 231 235 / var(--tw-text-opacity));\n}\n\n.dark\\\\:text-gray-300:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(209 213 219 / var(--tw-text-opacity));\n}\n\n.dark\\\\:text-gray-400:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(156 163 175 / var(--tw-text-opacity));\n}\n\n.dark\\\\:text-gray-500:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(107 114 128 / var(--tw-text-opacity));\n}\n\n.dark\\\\:text-gray-600:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(75 85 99 / var(--tw-text-opacity));\n}\n\n.dark\\\\:text-green-200:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(187 247 208 / var(--tw-text-opacity));\n}\n\n.dark\\\\:text-red-200:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(254 202 202 / var(--tw-text-opacity));\n}\n\n.dark\\\\:text-red-300:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(252 165 165 / var(--tw-text-opacity));\n}\n\n.dark\\\\:text-red-400:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(248 113 113 / var(--tw-text-opacity));\n}\n\n.dark\\\\:text-white:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity));\n}\n\n.dark\\\\:placeholder-gray-600:is(.dark *)::-moz-placeholder {\n --tw-placeholder-opacity: 1;\n color: rgb(75 85 99 / var(--tw-placeholder-opacity));\n}\n\n.dark\\\\:placeholder-gray-600:is(.dark *)::placeholder {\n --tw-placeholder-opacity: 1;\n color: rgb(75 85 99 / var(--tw-placeholder-opacity));\n}\n\n.dark\\\\:hover\\\\:bg-blue-600:hover:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(37 99 235 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:hover\\\\:bg-blue-800:hover:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(30 64 175 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:hover\\\\:bg-blue-900:hover:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(30 58 138 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:hover\\\\:bg-gray-600:hover:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(75 85 99 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:hover\\\\:bg-gray-700:hover:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(55 65 81 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:hover\\\\:bg-green-800:hover:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(22 101 52 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:hover\\\\:bg-purple-800:hover:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(107 33 168 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:hover\\\\:bg-red-600:hover:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(220 38 38 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:hover\\\\:bg-red-800:hover:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(153 27 27 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:hover\\\\:bg-red-900:hover:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(127 29 29 / var(--tw-bg-opacity));\n}\n\n.dark\\\\:hover\\\\:text-blue-300:hover:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(147 197 253 / var(--tw-text-opacity));\n}\n\n.dark\\\\:hover\\\\:text-gray-400:hover:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(156 163 175 / var(--tw-text-opacity));\n}\n\n.dark\\\\:hover\\\\:text-red-300:hover:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(252 165 165 / var(--tw-text-opacity));\n}\n\n.dark\\\\:hover\\\\:text-white:hover:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity));\n}\n\n@media (min-width: 640px) {\n\n .sm\\\\:left-auto {\n left: auto;\n }\n\n .sm\\\\:right-0 {\n right: 0px;\n }\n\n .sm\\\\:mb-0 {\n margin-bottom: 0px;\n }\n\n .sm\\\\:mr-3 {\n margin-right: 0.75rem;\n }\n\n .sm\\\\:h-auto {\n height: auto;\n }\n\n .sm\\\\:w-56 {\n width: 14rem;\n }\n\n .sm\\\\:w-72 {\n width: 18rem;\n }\n\n .sm\\\\:max-w-2xl {\n max-width: 42rem;\n }\n\n .sm\\\\:max-w-3xl {\n max-width: 48rem;\n }\n\n .sm\\\\:max-w-md {\n max-width: 28rem;\n }\n\n .sm\\\\:grid-flow-col {\n grid-auto-flow: column;\n }\n\n .sm\\\\:grid-cols-2 {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n\n .sm\\\\:grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n\n .sm\\\\:flex-row {\n flex-direction: row;\n }\n\n .sm\\\\:items-center {\n align-items: center;\n }\n\n .sm\\\\:rounded-lg {\n border-radius: 0.5rem;\n }\n\n .sm\\\\:p-6 {\n padding: 1.5rem;\n }\n\n .sm\\\\:px-6 {\n padding-left: 1.5rem;\n padding-right: 1.5rem;\n }\n\n .sm\\\\:shadow-2xl {\n --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);\n --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n }\n}\n\n@media (min-width: 768px) {\n\n .md\\\\:mb-0 {\n margin-bottom: 0px;\n }\n\n .md\\\\:block {\n display: block;\n }\n\n .md\\\\:flex {\n display: flex;\n }\n\n .md\\\\:hidden {\n display: none;\n }\n\n .md\\\\:w-auto {\n width: auto;\n }\n\n .md\\\\:max-w-3xl {\n max-width: 48rem;\n }\n\n .md\\\\:grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n\n .md\\\\:flex-row {\n flex-direction: row;\n }\n\n .md\\\\:items-center {\n align-items: center;\n }\n\n .md\\\\:justify-end {\n justify-content: flex-end;\n }\n\n .md\\\\:justify-between {\n justify-content: space-between;\n }\n\n .md\\\\:space-x-4 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-x-reverse: 0;\n margin-right: calc(1rem * var(--tw-space-x-reverse));\n margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));\n }\n\n .md\\\\:space-y-0 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0px * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0px * var(--tw-space-y-reverse));\n }\n\n .md\\\\:px-2 {\n padding-left: 0.5rem;\n padding-right: 0.5rem;\n }\n\n .md\\\\:px-6 {\n padding-left: 1.5rem;\n padding-right: 1.5rem;\n }\n}\n\n@media (min-width: 1024px) {\n\n .lg\\\\:grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n\n .lg\\\\:grid-cols-4 {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n }\n\n .lg\\\\:p-8 {\n padding: 2rem;\n }\n\n .lg\\\\:px-2 {\n padding-left: 0.5rem;\n padding-right: 0.5rem;\n }\n\n .lg\\\\:px-8 {\n padding-left: 2rem;\n padding-right: 2rem;\n }\n}\n\n@media (min-width: 1280px) {\n\n .xl\\\\:grid-cols-4 {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n }\n}\n\n`, \"\"]);\n// Exports\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://tududi/./frontend/styles/tailwind.css?./node_modules/css-loader/dist/cjs.js!./node_modules/postcss-loader/dist/cjs.js"); - -/***/ }), - -/***/ "./node_modules/css-loader/dist/runtime/api.js": -/*!*****************************************************!*\ - !*** ./node_modules/css-loader/dist/runtime/api.js ***! - \*****************************************************/ -/***/ ((module) => { - -"use strict"; -eval("\n\n/*\n MIT License http://www.opensource.org/licenses/mit-license.php\n Author Tobias Koppers @sokra\n*/\nmodule.exports = function (cssWithMappingToString) {\n var list = [];\n\n // return the list of modules as css string\n list.toString = function toString() {\n return this.map(function (item) {\n var content = \"\";\n var needLayer = typeof item[5] !== \"undefined\";\n if (item[4]) {\n content += \"@supports (\".concat(item[4], \") {\");\n }\n if (item[2]) {\n content += \"@media \".concat(item[2], \" {\");\n }\n if (needLayer) {\n content += \"@layer\".concat(item[5].length > 0 ? \" \".concat(item[5]) : \"\", \" {\");\n }\n content += cssWithMappingToString(item);\n if (needLayer) {\n content += \"}\";\n }\n if (item[2]) {\n content += \"}\";\n }\n if (item[4]) {\n content += \"}\";\n }\n return content;\n }).join(\"\");\n };\n\n // import a list of modules into the list\n list.i = function i(modules, media, dedupe, supports, layer) {\n if (typeof modules === \"string\") {\n modules = [[null, modules, undefined]];\n }\n var alreadyImportedModules = {};\n if (dedupe) {\n for (var k = 0; k < this.length; k++) {\n var id = this[k][0];\n if (id != null) {\n alreadyImportedModules[id] = true;\n }\n }\n }\n for (var _k = 0; _k < modules.length; _k++) {\n var item = [].concat(modules[_k]);\n if (dedupe && alreadyImportedModules[item[0]]) {\n continue;\n }\n if (typeof layer !== \"undefined\") {\n if (typeof item[5] === \"undefined\") {\n item[5] = layer;\n } else {\n item[1] = \"@layer\".concat(item[5].length > 0 ? \" \".concat(item[5]) : \"\", \" {\").concat(item[1], \"}\");\n item[5] = layer;\n }\n }\n if (media) {\n if (!item[2]) {\n item[2] = media;\n } else {\n item[1] = \"@media \".concat(item[2], \" {\").concat(item[1], \"}\");\n item[2] = media;\n }\n }\n if (supports) {\n if (!item[4]) {\n item[4] = \"\".concat(supports);\n } else {\n item[1] = \"@supports (\".concat(item[4], \") {\").concat(item[1], \"}\");\n item[4] = supports;\n }\n }\n list.push(item);\n }\n };\n return list;\n};\n\n//# sourceURL=webpack://tududi/./node_modules/css-loader/dist/runtime/api.js?"); - -/***/ }), - -/***/ "./node_modules/css-loader/dist/runtime/noSourceMaps.js": -/*!**************************************************************!*\ - !*** ./node_modules/css-loader/dist/runtime/noSourceMaps.js ***! - \**************************************************************/ -/***/ ((module) => { - -"use strict"; -eval("\n\nmodule.exports = function (i) {\n return i[1];\n};\n\n//# sourceURL=webpack://tududi/./node_modules/css-loader/dist/runtime/noSourceMaps.js?"); - -/***/ }), - -/***/ "./node_modules/error-stack-parser/error-stack-parser.js": -/*!***************************************************************!*\ - !*** ./node_modules/error-stack-parser/error-stack-parser.js ***! - \***************************************************************/ -/***/ (function(module, exports, __webpack_require__) { - -eval("var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(root, factory) {\n 'use strict';\n // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, Rhino, and browsers.\n\n /* istanbul ignore next */\n if (true) {\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! stackframe */ \"./node_modules/stackframe/stackframe.js\")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),\n\t\t__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?\n\t\t(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),\n\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n } else {}\n}(this, function ErrorStackParser(StackFrame) {\n 'use strict';\n\n var FIREFOX_SAFARI_STACK_REGEXP = /(^|@)\\S+:\\d+/;\n var CHROME_IE_STACK_REGEXP = /^\\s*at .*(\\S+:\\d+|\\(native\\))/m;\n var SAFARI_NATIVE_CODE_REGEXP = /^(eval@)?(\\[native code])?$/;\n\n return {\n /**\n * Given an Error object, extract the most information from it.\n *\n * @param {Error} error object\n * @return {Array} of StackFrames\n */\n parse: function ErrorStackParser$$parse(error) {\n if (typeof error.stacktrace !== 'undefined' || typeof error['opera#sourceloc'] !== 'undefined') {\n return this.parseOpera(error);\n } else if (error.stack && error.stack.match(CHROME_IE_STACK_REGEXP)) {\n return this.parseV8OrIE(error);\n } else if (error.stack) {\n return this.parseFFOrSafari(error);\n } else {\n throw new Error('Cannot parse given Error object');\n }\n },\n\n // Separate line and column numbers from a string of the form: (URI:Line:Column)\n extractLocation: function ErrorStackParser$$extractLocation(urlLike) {\n // Fail-fast but return locations like \"(native)\"\n if (urlLike.indexOf(':') === -1) {\n return [urlLike];\n }\n\n var regExp = /(.+?)(?::(\\d+))?(?::(\\d+))?$/;\n var parts = regExp.exec(urlLike.replace(/[()]/g, ''));\n return [parts[1], parts[2] || undefined, parts[3] || undefined];\n },\n\n parseV8OrIE: function ErrorStackParser$$parseV8OrIE(error) {\n var filtered = error.stack.split('\\n').filter(function(line) {\n return !!line.match(CHROME_IE_STACK_REGEXP);\n }, this);\n\n return filtered.map(function(line) {\n if (line.indexOf('(eval ') > -1) {\n // Throw away eval information until we implement stacktrace.js/stackframe#8\n line = line.replace(/eval code/g, 'eval').replace(/(\\(eval at [^()]*)|(,.*$)/g, '');\n }\n var sanitizedLine = line.replace(/^\\s+/, '').replace(/\\(eval code/g, '(').replace(/^.*?\\s+/, '');\n\n // capture and preseve the parenthesized location \"(/foo/my bar.js:12:87)\" in\n // case it has spaces in it, as the string is split on \\s+ later on\n var location = sanitizedLine.match(/ (\\(.+\\)$)/);\n\n // remove the parenthesized location from the line, if it was matched\n sanitizedLine = location ? sanitizedLine.replace(location[0], '') : sanitizedLine;\n\n // if a location was matched, pass it to extractLocation() otherwise pass all sanitizedLine\n // because this line doesn't have function name\n var locationParts = this.extractLocation(location ? location[1] : sanitizedLine);\n var functionName = location && sanitizedLine || undefined;\n var fileName = ['eval', ''].indexOf(locationParts[0]) > -1 ? undefined : locationParts[0];\n\n return new StackFrame({\n functionName: functionName,\n fileName: fileName,\n lineNumber: locationParts[1],\n columnNumber: locationParts[2],\n source: line\n });\n }, this);\n },\n\n parseFFOrSafari: function ErrorStackParser$$parseFFOrSafari(error) {\n var filtered = error.stack.split('\\n').filter(function(line) {\n return !line.match(SAFARI_NATIVE_CODE_REGEXP);\n }, this);\n\n return filtered.map(function(line) {\n // Throw away eval information until we implement stacktrace.js/stackframe#8\n if (line.indexOf(' > eval') > -1) {\n line = line.replace(/ line (\\d+)(?: > eval line \\d+)* > eval:\\d+:\\d+/g, ':$1');\n }\n\n if (line.indexOf('@') === -1 && line.indexOf(':') === -1) {\n // Safari eval frames only have function names and nothing else\n return new StackFrame({\n functionName: line\n });\n } else {\n var functionNameRegex = /((.*\".+\"[^@]*)?[^@]*)(?:@)/;\n var matches = line.match(functionNameRegex);\n var functionName = matches && matches[1] ? matches[1] : undefined;\n var locationParts = this.extractLocation(line.replace(functionNameRegex, ''));\n\n return new StackFrame({\n functionName: functionName,\n fileName: locationParts[0],\n lineNumber: locationParts[1],\n columnNumber: locationParts[2],\n source: line\n });\n }\n }, this);\n },\n\n parseOpera: function ErrorStackParser$$parseOpera(e) {\n if (!e.stacktrace || (e.message.indexOf('\\n') > -1 &&\n e.message.split('\\n').length > e.stacktrace.split('\\n').length)) {\n return this.parseOpera9(e);\n } else if (!e.stack) {\n return this.parseOpera10(e);\n } else {\n return this.parseOpera11(e);\n }\n },\n\n parseOpera9: function ErrorStackParser$$parseOpera9(e) {\n var lineRE = /Line (\\d+).*script (?:in )?(\\S+)/i;\n var lines = e.message.split('\\n');\n var result = [];\n\n for (var i = 2, len = lines.length; i < len; i += 2) {\n var match = lineRE.exec(lines[i]);\n if (match) {\n result.push(new StackFrame({\n fileName: match[2],\n lineNumber: match[1],\n source: lines[i]\n }));\n }\n }\n\n return result;\n },\n\n parseOpera10: function ErrorStackParser$$parseOpera10(e) {\n var lineRE = /Line (\\d+).*script (?:in )?(\\S+)(?:: In function (\\S+))?$/i;\n var lines = e.stacktrace.split('\\n');\n var result = [];\n\n for (var i = 0, len = lines.length; i < len; i += 2) {\n var match = lineRE.exec(lines[i]);\n if (match) {\n result.push(\n new StackFrame({\n functionName: match[3] || undefined,\n fileName: match[2],\n lineNumber: match[1],\n source: lines[i]\n })\n );\n }\n }\n\n return result;\n },\n\n // Opera 10.65+ Error.stack very similar to FF/Safari\n parseOpera11: function ErrorStackParser$$parseOpera11(error) {\n var filtered = error.stack.split('\\n').filter(function(line) {\n return !!line.match(FIREFOX_SAFARI_STACK_REGEXP) && !line.match(/^Error created at/);\n }, this);\n\n return filtered.map(function(line) {\n var tokens = line.split('@');\n var locationParts = this.extractLocation(tokens.pop());\n var functionCall = (tokens.shift() || '');\n var functionName = functionCall\n .replace(//, '$2')\n .replace(/\\([^)]*\\)/g, '') || undefined;\n var argsRaw;\n if (functionCall.match(/\\(([^)]*)\\)/)) {\n argsRaw = functionCall.replace(/^[^(]+\\(([^)]*)\\)$/, '$1');\n }\n var args = (argsRaw === undefined || argsRaw === '[arguments not available]') ?\n undefined : argsRaw.split(',');\n\n return new StackFrame({\n functionName: functionName,\n args: args,\n fileName: locationParts[0],\n lineNumber: locationParts[1],\n columnNumber: locationParts[2],\n source: line\n });\n }, this);\n }\n };\n}));\n\n\n//# sourceURL=webpack://tududi/./node_modules/error-stack-parser/error-stack-parser.js?"); - -/***/ }), - -/***/ "./node_modules/html-entities/lib/index.js": -/*!*************************************************!*\ - !*** ./node_modules/html-entities/lib/index.js ***! - \*************************************************/ -/***/ (function(__unused_webpack_module, exports, __webpack_require__) { - -"use strict"; -eval("var __assign=this&&this.__assign||function(){__assign=Object.assign||function(t){for(var s,i=1,n=arguments.length;i'\"&]/g,nonAscii:/[<>'\"&\\u0080-\\uD7FF\\uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]/g,nonAsciiPrintable:/[<>'\"&\\x01-\\x08\\x11-\\x15\\x17-\\x1F\\x7f-\\uD7FF\\uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]/g,nonAsciiPrintableOnly:/[\\x01-\\x08\\x11-\\x15\\x17-\\x1F\\x7f-\\uD7FF\\uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]/g,extensive:/[\\x01-\\x0c\\x0e-\\x1f\\x21-\\x2c\\x2e-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\x7d\\x7f-\\uD7FF\\uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]/g};var defaultEncodeOptions={mode:\"specialChars\",level:\"all\",numeric:\"decimal\"};function encode(text,_a){var _b=_a===void 0?defaultEncodeOptions:_a,_c=_b.mode,mode=_c===void 0?\"specialChars\":_c,_d=_b.numeric,numeric=_d===void 0?\"decimal\":_d,_e=_b.level,level=_e===void 0?\"all\":_e;if(!text){return\"\"}var encodeRegExp=encodeRegExps[mode];var references=allNamedReferences[level].characters;var isHex=numeric===\"hexadecimal\";return replaceUsingRegExp(text,encodeRegExp,(function(input){var result=references[input];if(!result){var code=input.length>1?surrogate_pairs_1.getCodePoint(input,0):input.charCodeAt(0);result=(isHex?\"&#x\"+code.toString(16):\"&#\"+code)+\";\"}return result}))}exports.encode=encode;var defaultDecodeOptions={scope:\"body\",level:\"all\"};var strict=/&(?:#\\d+|#[xX][\\da-fA-F]+|[0-9a-zA-Z]+);/g;var attribute=/&(?:#\\d+|#[xX][\\da-fA-F]+|[0-9a-zA-Z]+)[;=]?/g;var baseDecodeRegExps={xml:{strict:strict,attribute:attribute,body:named_references_1.bodyRegExps.xml},html4:{strict:strict,attribute:attribute,body:named_references_1.bodyRegExps.html4},html5:{strict:strict,attribute:attribute,body:named_references_1.bodyRegExps.html5}};var decodeRegExps=__assign(__assign({},baseDecodeRegExps),{all:baseDecodeRegExps.html5});var fromCharCode=String.fromCharCode;var outOfBoundsChar=fromCharCode(65533);var defaultDecodeEntityOptions={level:\"all\"};function getDecodedEntity(entity,references,isAttribute,isStrict){var decodeResult=entity;var decodeEntityLastChar=entity[entity.length-1];if(isAttribute&&decodeEntityLastChar===\"=\"){decodeResult=entity}else if(isStrict&&decodeEntityLastChar!==\";\"){decodeResult=entity}else{var decodeResultByReference=references[entity];if(decodeResultByReference){decodeResult=decodeResultByReference}else if(entity[0]===\"&\"&&entity[1]===\"#\"){var decodeSecondChar=entity[2];var decodeCode=decodeSecondChar==\"x\"||decodeSecondChar==\"X\"?parseInt(entity.substr(3),16):parseInt(entity.substr(2));decodeResult=decodeCode>=1114111?outOfBoundsChar:decodeCode>65535?surrogate_pairs_1.fromCodePoint(decodeCode):fromCharCode(numeric_unicode_map_1.numericUnicodeMap[decodeCode]||decodeCode)}}return decodeResult}function decodeEntity(entity,_a){var _b=(_a===void 0?defaultDecodeEntityOptions:_a).level,level=_b===void 0?\"all\":_b;if(!entity){return\"\"}return getDecodedEntity(entity,allNamedReferences[level].entities,false,false)}exports.decodeEntity=decodeEntity;function decode(text,_a){var _b=_a===void 0?defaultDecodeOptions:_a,_c=_b.level,level=_c===void 0?\"all\":_c,_d=_b.scope,scope=_d===void 0?level===\"xml\"?\"strict\":\"body\":_d;if(!text){return\"\"}var decodeRegExp=decodeRegExps[level][scope];var references=allNamedReferences[level].entities;var isAttribute=scope===\"attribute\";var isStrict=scope===\"strict\";return replaceUsingRegExp(text,decodeRegExp,(function(entity){return getDecodedEntity(entity,references,isAttribute,isStrict)}))}exports.decode=decode;\n//# sourceMappingURL=./index.js.map\n\n//# sourceURL=webpack://tududi/./node_modules/html-entities/lib/index.js?"); - -/***/ }), - -/***/ "./node_modules/html-entities/lib/named-references.js": -/*!************************************************************!*\ - !*** ./node_modules/html-entities/lib/named-references.js ***! - \************************************************************/ -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; -eval("Object.defineProperty(exports, \"__esModule\", ({value:true}));exports.bodyRegExps={xml:/&(?:#\\d+|#[xX][\\da-fA-F]+|[0-9a-zA-Z]+);?/g,html4:/∉|&(?:nbsp|iexcl|cent|pound|curren|yen|brvbar|sect|uml|copy|ordf|laquo|not|shy|reg|macr|deg|plusmn|sup2|sup3|acute|micro|para|middot|cedil|sup1|ordm|raquo|frac14|frac12|frac34|iquest|Agrave|Aacute|Acirc|Atilde|Auml|Aring|AElig|Ccedil|Egrave|Eacute|Ecirc|Euml|Igrave|Iacute|Icirc|Iuml|ETH|Ntilde|Ograve|Oacute|Ocirc|Otilde|Ouml|times|Oslash|Ugrave|Uacute|Ucirc|Uuml|Yacute|THORN|szlig|agrave|aacute|acirc|atilde|auml|aring|aelig|ccedil|egrave|eacute|ecirc|euml|igrave|iacute|icirc|iuml|eth|ntilde|ograve|oacute|ocirc|otilde|ouml|divide|oslash|ugrave|uacute|ucirc|uuml|yacute|thorn|yuml|quot|amp|lt|gt|#\\d+|#[xX][\\da-fA-F]+|[0-9a-zA-Z]+);?/g,html5:/·|℗|⋇|⪧|⩺|⋗|⦕|⩼|⪆|⥸|⋗|⋛|⪌|≷|≳|⪦|⩹|⋖|⋋|⋉|⥶|⩻|⦖|◃|⊴|◂|∉|⋹̸|⋵̸|∉|⋷|⋶|∌|∌|⋾|⋽|∥|⊠|⨱|⨰|&(?:AElig|AMP|Aacute|Acirc|Agrave|Aring|Atilde|Auml|COPY|Ccedil|ETH|Eacute|Ecirc|Egrave|Euml|GT|Iacute|Icirc|Igrave|Iuml|LT|Ntilde|Oacute|Ocirc|Ograve|Oslash|Otilde|Ouml|QUOT|REG|THORN|Uacute|Ucirc|Ugrave|Uuml|Yacute|aacute|acirc|acute|aelig|agrave|amp|aring|atilde|auml|brvbar|ccedil|cedil|cent|copy|curren|deg|divide|eacute|ecirc|egrave|eth|euml|frac12|frac14|frac34|gt|iacute|icirc|iexcl|igrave|iquest|iuml|laquo|lt|macr|micro|middot|nbsp|not|ntilde|oacute|ocirc|ograve|ordf|ordm|oslash|otilde|ouml|para|plusmn|pound|quot|raquo|reg|sect|shy|sup1|sup2|sup3|szlig|thorn|times|uacute|ucirc|ugrave|uml|uuml|yacute|yen|yuml|#\\d+|#[xX][\\da-fA-F]+|[0-9a-zA-Z]+);?/g};exports.namedReferences={xml:{entities:{\"<\":\"<\",\">\":\">\",\""\":'\"',\"'\":\"'\",\"&\":\"&\"},characters:{\"<\":\"<\",\">\":\">\",'\"':\""\",\"'\":\"'\",\"&\":\"&\"}},html4:{entities:{\"'\":\"'\",\" \":\" \",\" \":\" \",\"¡\":\"¡\",\"¡\":\"¡\",\"¢\":\"¢\",\"¢\":\"¢\",\"£\":\"£\",\"£\":\"£\",\"¤\":\"¤\",\"¤\":\"¤\",\"¥\":\"¥\",\"¥\":\"¥\",\"¦\":\"¦\",\"¦\":\"¦\",\"§\":\"§\",\"§\":\"§\",\"¨\":\"¨\",\"¨\":\"¨\",\"©\":\"©\",\"©\":\"©\",\"ª\":\"ª\",\"ª\":\"ª\",\"«\":\"«\",\"«\":\"«\",\"¬\":\"¬\",\"¬\":\"¬\",\"­\":\"­\",\"­\":\"­\",\"®\":\"®\",\"®\":\"®\",\"¯\":\"¯\",\"¯\":\"¯\",\"°\":\"°\",\"°\":\"°\",\"±\":\"±\",\"±\":\"±\",\"²\":\"²\",\"²\":\"²\",\"³\":\"³\",\"³\":\"³\",\"´\":\"´\",\"´\":\"´\",\"µ\":\"µ\",\"µ\":\"µ\",\"¶\":\"¶\",\"¶\":\"¶\",\"·\":\"·\",\"·\":\"·\",\"¸\":\"¸\",\"¸\":\"¸\",\"¹\":\"¹\",\"¹\":\"¹\",\"º\":\"º\",\"º\":\"º\",\"»\":\"»\",\"»\":\"»\",\"¼\":\"¼\",\"¼\":\"¼\",\"½\":\"½\",\"½\":\"½\",\"¾\":\"¾\",\"¾\":\"¾\",\"¿\":\"¿\",\"¿\":\"¿\",\"À\":\"À\",\"À\":\"À\",\"Á\":\"Á\",\"Á\":\"Á\",\"Â\":\"Â\",\"Â\":\"Â\",\"Ã\":\"Ã\",\"Ã\":\"Ã\",\"Ä\":\"Ä\",\"Ä\":\"Ä\",\"Å\":\"Å\",\"Å\":\"Å\",\"Æ\":\"Æ\",\"Æ\":\"Æ\",\"Ç\":\"Ç\",\"Ç\":\"Ç\",\"È\":\"È\",\"È\":\"È\",\"É\":\"É\",\"É\":\"É\",\"Ê\":\"Ê\",\"Ê\":\"Ê\",\"Ë\":\"Ë\",\"Ë\":\"Ë\",\"Ì\":\"Ì\",\"Ì\":\"Ì\",\"Í\":\"Í\",\"Í\":\"Í\",\"Î\":\"Î\",\"Î\":\"Î\",\"Ï\":\"Ï\",\"Ï\":\"Ï\",\"Ð\":\"Ð\",\"Ð\":\"Ð\",\"Ñ\":\"Ñ\",\"Ñ\":\"Ñ\",\"Ò\":\"Ò\",\"Ò\":\"Ò\",\"Ó\":\"Ó\",\"Ó\":\"Ó\",\"Ô\":\"Ô\",\"Ô\":\"Ô\",\"Õ\":\"Õ\",\"Õ\":\"Õ\",\"Ö\":\"Ö\",\"Ö\":\"Ö\",\"×\":\"×\",\"×\":\"×\",\"Ø\":\"Ø\",\"Ø\":\"Ø\",\"Ù\":\"Ù\",\"Ù\":\"Ù\",\"Ú\":\"Ú\",\"Ú\":\"Ú\",\"Û\":\"Û\",\"Û\":\"Û\",\"Ü\":\"Ü\",\"Ü\":\"Ü\",\"Ý\":\"Ý\",\"Ý\":\"Ý\",\"Þ\":\"Þ\",\"Þ\":\"Þ\",\"ß\":\"ß\",\"ß\":\"ß\",\"à\":\"à\",\"à\":\"à\",\"á\":\"á\",\"á\":\"á\",\"â\":\"â\",\"â\":\"â\",\"ã\":\"ã\",\"ã\":\"ã\",\"ä\":\"ä\",\"ä\":\"ä\",\"å\":\"å\",\"å\":\"å\",\"æ\":\"æ\",\"æ\":\"æ\",\"ç\":\"ç\",\"ç\":\"ç\",\"è\":\"è\",\"è\":\"è\",\"é\":\"é\",\"é\":\"é\",\"ê\":\"ê\",\"ê\":\"ê\",\"ë\":\"ë\",\"ë\":\"ë\",\"ì\":\"ì\",\"ì\":\"ì\",\"í\":\"í\",\"í\":\"í\",\"î\":\"î\",\"î\":\"î\",\"ï\":\"ï\",\"ï\":\"ï\",\"ð\":\"ð\",\"ð\":\"ð\",\"ñ\":\"ñ\",\"ñ\":\"ñ\",\"ò\":\"ò\",\"ò\":\"ò\",\"ó\":\"ó\",\"ó\":\"ó\",\"ô\":\"ô\",\"ô\":\"ô\",\"õ\":\"õ\",\"õ\":\"õ\",\"ö\":\"ö\",\"ö\":\"ö\",\"÷\":\"÷\",\"÷\":\"÷\",\"ø\":\"ø\",\"ø\":\"ø\",\"ù\":\"ù\",\"ù\":\"ù\",\"ú\":\"ú\",\"ú\":\"ú\",\"û\":\"û\",\"û\":\"û\",\"ü\":\"ü\",\"ü\":\"ü\",\"ý\":\"ý\",\"ý\":\"ý\",\"þ\":\"þ\",\"þ\":\"þ\",\"ÿ\":\"ÿ\",\"ÿ\":\"ÿ\",\""\":'\"',\""\":'\"',\"&\":\"&\",\"&\":\"&\",\"<\":\"<\",\"<\":\"<\",\">\":\">\",\">\":\">\",\"Œ\":\"Œ\",\"œ\":\"œ\",\"Š\":\"Š\",\"š\":\"š\",\"Ÿ\":\"Ÿ\",\"ˆ\":\"ˆ\",\"˜\":\"˜\",\" \":\" \",\" \":\" \",\" \":\" \",\"‌\":\"‌\",\"‍\":\"‍\",\"‎\":\"‎\",\"‏\":\"‏\",\"–\":\"–\",\"—\":\"—\",\"‘\":\"‘\",\"’\":\"’\",\"‚\":\"‚\",\"“\":\"“\",\"”\":\"”\",\"„\":\"„\",\"†\":\"†\",\"‡\":\"‡\",\"‰\":\"‰\",\"‹\":\"‹\",\"›\":\"›\",\"€\":\"€\",\"ƒ\":\"ƒ\",\"Α\":\"Α\",\"Β\":\"Β\",\"Γ\":\"Γ\",\"Δ\":\"Δ\",\"Ε\":\"Ε\",\"Ζ\":\"Ζ\",\"Η\":\"Η\",\"Θ\":\"Θ\",\"Ι\":\"Ι\",\"Κ\":\"Κ\",\"Λ\":\"Λ\",\"Μ\":\"Μ\",\"Ν\":\"Ν\",\"Ξ\":\"Ξ\",\"Ο\":\"Ο\",\"Π\":\"Π\",\"Ρ\":\"Ρ\",\"Σ\":\"Σ\",\"Τ\":\"Τ\",\"Υ\":\"Υ\",\"Φ\":\"Φ\",\"Χ\":\"Χ\",\"Ψ\":\"Ψ\",\"Ω\":\"Ω\",\"α\":\"α\",\"β\":\"β\",\"γ\":\"γ\",\"δ\":\"δ\",\"ε\":\"ε\",\"ζ\":\"ζ\",\"η\":\"η\",\"θ\":\"θ\",\"ι\":\"ι\",\"κ\":\"κ\",\"λ\":\"λ\",\"μ\":\"μ\",\"ν\":\"ν\",\"ξ\":\"ξ\",\"ο\":\"ο\",\"π\":\"π\",\"ρ\":\"ρ\",\"ς\":\"ς\",\"σ\":\"σ\",\"τ\":\"τ\",\"υ\":\"υ\",\"φ\":\"φ\",\"χ\":\"χ\",\"ψ\":\"ψ\",\"ω\":\"ω\",\"ϑ\":\"ϑ\",\"ϒ\":\"ϒ\",\"ϖ\":\"ϖ\",\"•\":\"•\",\"…\":\"…\",\"′\":\"′\",\"″\":\"″\",\"‾\":\"‾\",\"⁄\":\"⁄\",\"℘\":\"℘\",\"ℑ\":\"ℑ\",\"ℜ\":\"ℜ\",\"™\":\"™\",\"ℵ\":\"ℵ\",\"←\":\"←\",\"↑\":\"↑\",\"→\":\"→\",\"↓\":\"↓\",\"↔\":\"↔\",\"↵\":\"↵\",\"⇐\":\"⇐\",\"⇑\":\"⇑\",\"⇒\":\"⇒\",\"⇓\":\"⇓\",\"⇔\":\"⇔\",\"∀\":\"∀\",\"∂\":\"∂\",\"∃\":\"∃\",\"∅\":\"∅\",\"∇\":\"∇\",\"∈\":\"∈\",\"∉\":\"∉\",\"∋\":\"∋\",\"∏\":\"∏\",\"∑\":\"∑\",\"−\":\"−\",\"∗\":\"∗\",\"√\":\"√\",\"∝\":\"∝\",\"∞\":\"∞\",\"∠\":\"∠\",\"∧\":\"∧\",\"∨\":\"∨\",\"∩\":\"∩\",\"∪\":\"∪\",\"∫\":\"∫\",\"∴\":\"∴\",\"∼\":\"∼\",\"≅\":\"≅\",\"≈\":\"≈\",\"≠\":\"≠\",\"≡\":\"≡\",\"≤\":\"≤\",\"≥\":\"≥\",\"⊂\":\"⊂\",\"⊃\":\"⊃\",\"⊄\":\"⊄\",\"⊆\":\"⊆\",\"⊇\":\"⊇\",\"⊕\":\"⊕\",\"⊗\":\"⊗\",\"⊥\":\"⊥\",\"⋅\":\"⋅\",\"⌈\":\"⌈\",\"⌉\":\"⌉\",\"⌊\":\"⌊\",\"⌋\":\"⌋\",\"⟨\":\"〈\",\"⟩\":\"〉\",\"◊\":\"◊\",\"♠\":\"♠\",\"♣\":\"♣\",\"♥\":\"♥\",\"♦\":\"♦\"},characters:{\"'\":\"'\",\" \":\" \",\"¡\":\"¡\",\"¢\":\"¢\",\"£\":\"£\",\"¤\":\"¤\",\"¥\":\"¥\",\"¦\":\"¦\",\"§\":\"§\",\"¨\":\"¨\",\"©\":\"©\",\"ª\":\"ª\",\"«\":\"«\",\"¬\":\"¬\",\"­\":\"­\",\"®\":\"®\",\"¯\":\"¯\",\"°\":\"°\",\"±\":\"±\",\"²\":\"²\",\"³\":\"³\",\"´\":\"´\",\"µ\":\"µ\",\"¶\":\"¶\",\"·\":\"·\",\"¸\":\"¸\",\"¹\":\"¹\",\"º\":\"º\",\"»\":\"»\",\"¼\":\"¼\",\"½\":\"½\",\"¾\":\"¾\",\"¿\":\"¿\",\"À\":\"À\",\"Á\":\"Á\",\"Â\":\"Â\",\"Ã\":\"Ã\",\"Ä\":\"Ä\",\"Å\":\"Å\",\"Æ\":\"Æ\",\"Ç\":\"Ç\",\"È\":\"È\",\"É\":\"É\",\"Ê\":\"Ê\",\"Ë\":\"Ë\",\"Ì\":\"Ì\",\"Í\":\"Í\",\"Î\":\"Î\",\"Ï\":\"Ï\",\"Ð\":\"Ð\",\"Ñ\":\"Ñ\",\"Ò\":\"Ò\",\"Ó\":\"Ó\",\"Ô\":\"Ô\",\"Õ\":\"Õ\",\"Ö\":\"Ö\",\"×\":\"×\",\"Ø\":\"Ø\",\"Ù\":\"Ù\",\"Ú\":\"Ú\",\"Û\":\"Û\",\"Ü\":\"Ü\",\"Ý\":\"Ý\",\"Þ\":\"Þ\",\"ß\":\"ß\",\"à\":\"à\",\"á\":\"á\",\"â\":\"â\",\"ã\":\"ã\",\"ä\":\"ä\",\"å\":\"å\",\"æ\":\"æ\",\"ç\":\"ç\",\"è\":\"è\",\"é\":\"é\",\"ê\":\"ê\",\"ë\":\"ë\",\"ì\":\"ì\",\"í\":\"í\",\"î\":\"î\",\"ï\":\"ï\",\"ð\":\"ð\",\"ñ\":\"ñ\",\"ò\":\"ò\",\"ó\":\"ó\",\"ô\":\"ô\",\"õ\":\"õ\",\"ö\":\"ö\",\"÷\":\"÷\",\"ø\":\"ø\",\"ù\":\"ù\",\"ú\":\"ú\",\"û\":\"û\",\"ü\":\"ü\",\"ý\":\"ý\",\"þ\":\"þ\",\"ÿ\":\"ÿ\",'\"':\""\",\"&\":\"&\",\"<\":\"<\",\">\":\">\",\"Œ\":\"Œ\",\"œ\":\"œ\",\"Š\":\"Š\",\"š\":\"š\",\"Ÿ\":\"Ÿ\",\"ˆ\":\"ˆ\",\"˜\":\"˜\",\" \":\" \",\" \":\" \",\" \":\" \",\"‌\":\"‌\",\"‍\":\"‍\",\"‎\":\"‎\",\"‏\":\"‏\",\"–\":\"–\",\"—\":\"—\",\"‘\":\"‘\",\"’\":\"’\",\"‚\":\"‚\",\"“\":\"“\",\"”\":\"”\",\"„\":\"„\",\"†\":\"†\",\"‡\":\"‡\",\"‰\":\"‰\",\"‹\":\"‹\",\"›\":\"›\",\"€\":\"€\",\"ƒ\":\"ƒ\",\"Α\":\"Α\",\"Β\":\"Β\",\"Γ\":\"Γ\",\"Δ\":\"Δ\",\"Ε\":\"Ε\",\"Ζ\":\"Ζ\",\"Η\":\"Η\",\"Θ\":\"Θ\",\"Ι\":\"Ι\",\"Κ\":\"Κ\",\"Λ\":\"Λ\",\"Μ\":\"Μ\",\"Ν\":\"Ν\",\"Ξ\":\"Ξ\",\"Ο\":\"Ο\",\"Π\":\"Π\",\"Ρ\":\"Ρ\",\"Σ\":\"Σ\",\"Τ\":\"Τ\",\"Υ\":\"Υ\",\"Φ\":\"Φ\",\"Χ\":\"Χ\",\"Ψ\":\"Ψ\",\"Ω\":\"Ω\",\"α\":\"α\",\"β\":\"β\",\"γ\":\"γ\",\"δ\":\"δ\",\"ε\":\"ε\",\"ζ\":\"ζ\",\"η\":\"η\",\"θ\":\"θ\",\"ι\":\"ι\",\"κ\":\"κ\",\"λ\":\"λ\",\"μ\":\"μ\",\"ν\":\"ν\",\"ξ\":\"ξ\",\"ο\":\"ο\",\"π\":\"π\",\"ρ\":\"ρ\",\"ς\":\"ς\",\"σ\":\"σ\",\"τ\":\"τ\",\"υ\":\"υ\",\"φ\":\"φ\",\"χ\":\"χ\",\"ψ\":\"ψ\",\"ω\":\"ω\",\"ϑ\":\"ϑ\",\"ϒ\":\"ϒ\",\"ϖ\":\"ϖ\",\"•\":\"•\",\"…\":\"…\",\"′\":\"′\",\"″\":\"″\",\"‾\":\"‾\",\"⁄\":\"⁄\",\"℘\":\"℘\",\"ℑ\":\"ℑ\",\"ℜ\":\"ℜ\",\"™\":\"™\",\"ℵ\":\"ℵ\",\"←\":\"←\",\"↑\":\"↑\",\"→\":\"→\",\"↓\":\"↓\",\"↔\":\"↔\",\"↵\":\"↵\",\"⇐\":\"⇐\",\"⇑\":\"⇑\",\"⇒\":\"⇒\",\"⇓\":\"⇓\",\"⇔\":\"⇔\",\"∀\":\"∀\",\"∂\":\"∂\",\"∃\":\"∃\",\"∅\":\"∅\",\"∇\":\"∇\",\"∈\":\"∈\",\"∉\":\"∉\",\"∋\":\"∋\",\"∏\":\"∏\",\"∑\":\"∑\",\"−\":\"−\",\"∗\":\"∗\",\"√\":\"√\",\"∝\":\"∝\",\"∞\":\"∞\",\"∠\":\"∠\",\"∧\":\"∧\",\"∨\":\"∨\",\"∩\":\"∩\",\"∪\":\"∪\",\"∫\":\"∫\",\"∴\":\"∴\",\"∼\":\"∼\",\"≅\":\"≅\",\"≈\":\"≈\",\"≠\":\"≠\",\"≡\":\"≡\",\"≤\":\"≤\",\"≥\":\"≥\",\"⊂\":\"⊂\",\"⊃\":\"⊃\",\"⊄\":\"⊄\",\"⊆\":\"⊆\",\"⊇\":\"⊇\",\"⊕\":\"⊕\",\"⊗\":\"⊗\",\"⊥\":\"⊥\",\"⋅\":\"⋅\",\"⌈\":\"⌈\",\"⌉\":\"⌉\",\"⌊\":\"⌊\",\"⌋\":\"⌋\",\"〈\":\"⟨\",\"〉\":\"⟩\",\"◊\":\"◊\",\"♠\":\"♠\",\"♣\":\"♣\",\"♥\":\"♥\",\"♦\":\"♦\"}},html5:{entities:{\"Æ\":\"Æ\",\"Æ\":\"Æ\",\"&\":\"&\",\"&\":\"&\",\"Á\":\"Á\",\"Á\":\"Á\",\"Ă\":\"Ă\",\"Â\":\"Â\",\"Â\":\"Â\",\"А\":\"А\",\"𝔄\":\"𝔄\",\"À\":\"À\",\"À\":\"À\",\"Α\":\"Α\",\"Ā\":\"Ā\",\"⩓\":\"⩓\",\"Ą\":\"Ą\",\"𝔸\":\"𝔸\",\"⁡\":\"⁡\",\"Å\":\"Å\",\"Å\":\"Å\",\"𝒜\":\"𝒜\",\"≔\":\"≔\",\"Ã\":\"Ã\",\"Ã\":\"Ã\",\"Ä\":\"Ä\",\"Ä\":\"Ä\",\"∖\":\"∖\",\"⫧\":\"⫧\",\"⌆\":\"⌆\",\"Б\":\"Б\",\"∵\":\"∵\",\"ℬ\":\"ℬ\",\"Β\":\"Β\",\"𝔅\":\"𝔅\",\"𝔹\":\"𝔹\",\"˘\":\"˘\",\"ℬ\":\"ℬ\",\"≎\":\"≎\",\"Ч\":\"Ч\",\"©\":\"©\",\"©\":\"©\",\"Ć\":\"Ć\",\"⋒\":\"⋒\",\"ⅅ\":\"ⅅ\",\"ℭ\":\"ℭ\",\"Č\":\"Č\",\"Ç\":\"Ç\",\"Ç\":\"Ç\",\"Ĉ\":\"Ĉ\",\"∰\":\"∰\",\"Ċ\":\"Ċ\",\"¸\":\"¸\",\"·\":\"·\",\"ℭ\":\"ℭ\",\"Χ\":\"Χ\",\"⊙\":\"⊙\",\"⊖\":\"⊖\",\"⊕\":\"⊕\",\"⊗\":\"⊗\",\"∲\":\"∲\",\"”\":\"”\",\"’\":\"’\",\"∷\":\"∷\",\"⩴\":\"⩴\",\"≡\":\"≡\",\"∯\":\"∯\",\"∮\":\"∮\",\"ℂ\":\"ℂ\",\"∐\":\"∐\",\"∳\":\"∳\",\"⨯\":\"⨯\",\"𝒞\":\"𝒞\",\"⋓\":\"⋓\",\"≍\":\"≍\",\"ⅅ\":\"ⅅ\",\"⤑\":\"⤑\",\"Ђ\":\"Ђ\",\"Ѕ\":\"Ѕ\",\"Џ\":\"Џ\",\"‡\":\"‡\",\"↡\":\"↡\",\"⫤\":\"⫤\",\"Ď\":\"Ď\",\"Д\":\"Д\",\"∇\":\"∇\",\"Δ\":\"Δ\",\"𝔇\":\"𝔇\",\"´\":\"´\",\"˙\":\"˙\",\"˝\":\"˝\",\"`\":\"`\",\"˜\":\"˜\",\"⋄\":\"⋄\",\"ⅆ\":\"ⅆ\",\"𝔻\":\"𝔻\",\"¨\":\"¨\",\"⃜\":\"⃜\",\"≐\":\"≐\",\"∯\":\"∯\",\"¨\":\"¨\",\"⇓\":\"⇓\",\"⇐\":\"⇐\",\"⇔\":\"⇔\",\"⫤\":\"⫤\",\"⟸\":\"⟸\",\"⟺\":\"⟺\",\"⟹\":\"⟹\",\"⇒\":\"⇒\",\"⊨\":\"⊨\",\"⇑\":\"⇑\",\"⇕\":\"⇕\",\"∥\":\"∥\",\"↓\":\"↓\",\"⤓\":\"⤓\",\"⇵\":\"⇵\",\"̑\":\"̑\",\"⥐\":\"⥐\",\"⥞\":\"⥞\",\"↽\":\"↽\",\"⥖\":\"⥖\",\"⥟\":\"⥟\",\"⇁\":\"⇁\",\"⥗\":\"⥗\",\"⊤\":\"⊤\",\"↧\":\"↧\",\"⇓\":\"⇓\",\"𝒟\":\"𝒟\",\"Đ\":\"Đ\",\"Ŋ\":\"Ŋ\",\"Ð\":\"Ð\",\"Ð\":\"Ð\",\"É\":\"É\",\"É\":\"É\",\"Ě\":\"Ě\",\"Ê\":\"Ê\",\"Ê\":\"Ê\",\"Э\":\"Э\",\"Ė\":\"Ė\",\"𝔈\":\"𝔈\",\"È\":\"È\",\"È\":\"È\",\"∈\":\"∈\",\"Ē\":\"Ē\",\"◻\":\"◻\",\"▫\":\"▫\",\"Ę\":\"Ę\",\"𝔼\":\"𝔼\",\"Ε\":\"Ε\",\"⩵\":\"⩵\",\"≂\":\"≂\",\"⇌\":\"⇌\",\"ℰ\":\"ℰ\",\"⩳\":\"⩳\",\"Η\":\"Η\",\"Ë\":\"Ë\",\"Ë\":\"Ë\",\"∃\":\"∃\",\"ⅇ\":\"ⅇ\",\"Ф\":\"Ф\",\"𝔉\":\"𝔉\",\"◼\":\"◼\",\"▪\":\"▪\",\"𝔽\":\"𝔽\",\"∀\":\"∀\",\"ℱ\":\"ℱ\",\"ℱ\":\"ℱ\",\"Ѓ\":\"Ѓ\",\">\":\">\",\">\":\">\",\"Γ\":\"Γ\",\"Ϝ\":\"Ϝ\",\"Ğ\":\"Ğ\",\"Ģ\":\"Ģ\",\"Ĝ\":\"Ĝ\",\"Г\":\"Г\",\"Ġ\":\"Ġ\",\"𝔊\":\"𝔊\",\"⋙\":\"⋙\",\"𝔾\":\"𝔾\",\"≥\":\"≥\",\"⋛\":\"⋛\",\"≧\":\"≧\",\"⪢\":\"⪢\",\"≷\":\"≷\",\"⩾\":\"⩾\",\"≳\":\"≳\",\"𝒢\":\"𝒢\",\"≫\":\"≫\",\"Ъ\":\"Ъ\",\"ˇ\":\"ˇ\",\"^\":\"^\",\"Ĥ\":\"Ĥ\",\"ℌ\":\"ℌ\",\"ℋ\":\"ℋ\",\"ℍ\":\"ℍ\",\"─\":\"─\",\"ℋ\":\"ℋ\",\"Ħ\":\"Ħ\",\"≎\":\"≎\",\"≏\":\"≏\",\"Е\":\"Е\",\"IJ\":\"IJ\",\"Ё\":\"Ё\",\"Í\":\"Í\",\"Í\":\"Í\",\"Î\":\"Î\",\"Î\":\"Î\",\"И\":\"И\",\"İ\":\"İ\",\"ℑ\":\"ℑ\",\"Ì\":\"Ì\",\"Ì\":\"Ì\",\"ℑ\":\"ℑ\",\"Ī\":\"Ī\",\"ⅈ\":\"ⅈ\",\"⇒\":\"⇒\",\"∬\":\"∬\",\"∫\":\"∫\",\"⋂\":\"⋂\",\"⁣\":\"⁣\",\"⁢\":\"⁢\",\"Į\":\"Į\",\"𝕀\":\"𝕀\",\"Ι\":\"Ι\",\"ℐ\":\"ℐ\",\"Ĩ\":\"Ĩ\",\"І\":\"І\",\"Ï\":\"Ï\",\"Ï\":\"Ï\",\"Ĵ\":\"Ĵ\",\"Й\":\"Й\",\"𝔍\":\"𝔍\",\"𝕁\":\"𝕁\",\"𝒥\":\"𝒥\",\"Ј\":\"Ј\",\"Є\":\"Є\",\"Х\":\"Х\",\"Ќ\":\"Ќ\",\"Κ\":\"Κ\",\"Ķ\":\"Ķ\",\"К\":\"К\",\"𝔎\":\"𝔎\",\"𝕂\":\"𝕂\",\"𝒦\":\"𝒦\",\"Љ\":\"Љ\",\"<\":\"<\",\"<\":\"<\",\"Ĺ\":\"Ĺ\",\"Λ\":\"Λ\",\"⟪\":\"⟪\",\"ℒ\":\"ℒ\",\"↞\":\"↞\",\"Ľ\":\"Ľ\",\"Ļ\":\"Ļ\",\"Л\":\"Л\",\"⟨\":\"⟨\",\"←\":\"←\",\"⇤\":\"⇤\",\"⇆\":\"⇆\",\"⌈\":\"⌈\",\"⟦\":\"⟦\",\"⥡\":\"⥡\",\"⇃\":\"⇃\",\"⥙\":\"⥙\",\"⌊\":\"⌊\",\"↔\":\"↔\",\"⥎\":\"⥎\",\"⊣\":\"⊣\",\"↤\":\"↤\",\"⥚\":\"⥚\",\"⊲\":\"⊲\",\"⧏\":\"⧏\",\"⊴\":\"⊴\",\"⥑\":\"⥑\",\"⥠\":\"⥠\",\"↿\":\"↿\",\"⥘\":\"⥘\",\"↼\":\"↼\",\"⥒\":\"⥒\",\"⇐\":\"⇐\",\"⇔\":\"⇔\",\"⋚\":\"⋚\",\"≦\":\"≦\",\"≶\":\"≶\",\"⪡\":\"⪡\",\"⩽\":\"⩽\",\"≲\":\"≲\",\"𝔏\":\"𝔏\",\"⋘\":\"⋘\",\"⇚\":\"⇚\",\"Ŀ\":\"Ŀ\",\"⟵\":\"⟵\",\"⟷\":\"⟷\",\"⟶\":\"⟶\",\"⟸\":\"⟸\",\"⟺\":\"⟺\",\"⟹\":\"⟹\",\"𝕃\":\"𝕃\",\"↙\":\"↙\",\"↘\":\"↘\",\"ℒ\":\"ℒ\",\"↰\":\"↰\",\"Ł\":\"Ł\",\"≪\":\"≪\",\"⤅\":\"⤅\",\"М\":\"М\",\" \":\" \",\"ℳ\":\"ℳ\",\"𝔐\":\"𝔐\",\"∓\":\"∓\",\"𝕄\":\"𝕄\",\"ℳ\":\"ℳ\",\"Μ\":\"Μ\",\"Њ\":\"Њ\",\"Ń\":\"Ń\",\"Ň\":\"Ň\",\"Ņ\":\"Ņ\",\"Н\":\"Н\",\"​\":\"​\",\"​\":\"​\",\"​\":\"​\",\"​\":\"​\",\"≫\":\"≫\",\"≪\":\"≪\",\" \":\"\\n\",\"𝔑\":\"𝔑\",\"⁠\":\"⁠\",\" \":\" \",\"ℕ\":\"ℕ\",\"⫬\":\"⫬\",\"≢\":\"≢\",\"≭\":\"≭\",\"∦\":\"∦\",\"∉\":\"∉\",\"≠\":\"≠\",\"≂̸\":\"≂̸\",\"∄\":\"∄\",\"≯\":\"≯\",\"≱\":\"≱\",\"≧̸\":\"≧̸\",\"≫̸\":\"≫̸\",\"≹\":\"≹\",\"⩾̸\":\"⩾̸\",\"≵\":\"≵\",\"≎̸\":\"≎̸\",\"≏̸\":\"≏̸\",\"⋪\":\"⋪\",\"⧏̸\":\"⧏̸\",\"⋬\":\"⋬\",\"≮\":\"≮\",\"≰\":\"≰\",\"≸\":\"≸\",\"≪̸\":\"≪̸\",\"⩽̸\":\"⩽̸\",\"≴\":\"≴\",\"⪢̸\":\"⪢̸\",\"⪡̸\":\"⪡̸\",\"⊀\":\"⊀\",\"⪯̸\":\"⪯̸\",\"⋠\":\"⋠\",\"∌\":\"∌\",\"⋫\":\"⋫\",\"⧐̸\":\"⧐̸\",\"⋭\":\"⋭\",\"⊏̸\":\"⊏̸\",\"⋢\":\"⋢\",\"⊐̸\":\"⊐̸\",\"⋣\":\"⋣\",\"⊂⃒\":\"⊂⃒\",\"⊈\":\"⊈\",\"⊁\":\"⊁\",\"⪰̸\":\"⪰̸\",\"⋡\":\"⋡\",\"≿̸\":\"≿̸\",\"⊃⃒\":\"⊃⃒\",\"⊉\":\"⊉\",\"≁\":\"≁\",\"≄\":\"≄\",\"≇\":\"≇\",\"≉\":\"≉\",\"∤\":\"∤\",\"𝒩\":\"𝒩\",\"Ñ\":\"Ñ\",\"Ñ\":\"Ñ\",\"Ν\":\"Ν\",\"Œ\":\"Œ\",\"Ó\":\"Ó\",\"Ó\":\"Ó\",\"Ô\":\"Ô\",\"Ô\":\"Ô\",\"О\":\"О\",\"Ő\":\"Ő\",\"𝔒\":\"𝔒\",\"Ò\":\"Ò\",\"Ò\":\"Ò\",\"Ō\":\"Ō\",\"Ω\":\"Ω\",\"Ο\":\"Ο\",\"𝕆\":\"𝕆\",\"“\":\"“\",\"‘\":\"‘\",\"⩔\":\"⩔\",\"𝒪\":\"𝒪\",\"Ø\":\"Ø\",\"Ø\":\"Ø\",\"Õ\":\"Õ\",\"Õ\":\"Õ\",\"⨷\":\"⨷\",\"Ö\":\"Ö\",\"Ö\":\"Ö\",\"‾\":\"‾\",\"⏞\":\"⏞\",\"⎴\":\"⎴\",\"⏜\":\"⏜\",\"∂\":\"∂\",\"П\":\"П\",\"𝔓\":\"𝔓\",\"Φ\":\"Φ\",\"Π\":\"Π\",\"±\":\"±\",\"ℌ\":\"ℌ\",\"ℙ\":\"ℙ\",\"⪻\":\"⪻\",\"≺\":\"≺\",\"⪯\":\"⪯\",\"≼\":\"≼\",\"≾\":\"≾\",\"″\":\"″\",\"∏\":\"∏\",\"∷\":\"∷\",\"∝\":\"∝\",\"𝒫\":\"𝒫\",\"Ψ\":\"Ψ\",\""\":'\"',\""\":'\"',\"𝔔\":\"𝔔\",\"ℚ\":\"ℚ\",\"𝒬\":\"𝒬\",\"⤐\":\"⤐\",\"®\":\"®\",\"®\":\"®\",\"Ŕ\":\"Ŕ\",\"⟫\":\"⟫\",\"↠\":\"↠\",\"⤖\":\"⤖\",\"Ř\":\"Ř\",\"Ŗ\":\"Ŗ\",\"Р\":\"Р\",\"ℜ\":\"ℜ\",\"∋\":\"∋\",\"⇋\":\"⇋\",\"⥯\":\"⥯\",\"ℜ\":\"ℜ\",\"Ρ\":\"Ρ\",\"⟩\":\"⟩\",\"→\":\"→\",\"⇥\":\"⇥\",\"⇄\":\"⇄\",\"⌉\":\"⌉\",\"⟧\":\"⟧\",\"⥝\":\"⥝\",\"⇂\":\"⇂\",\"⥕\":\"⥕\",\"⌋\":\"⌋\",\"⊢\":\"⊢\",\"↦\":\"↦\",\"⥛\":\"⥛\",\"⊳\":\"⊳\",\"⧐\":\"⧐\",\"⊵\":\"⊵\",\"⥏\":\"⥏\",\"⥜\":\"⥜\",\"↾\":\"↾\",\"⥔\":\"⥔\",\"⇀\":\"⇀\",\"⥓\":\"⥓\",\"⇒\":\"⇒\",\"ℝ\":\"ℝ\",\"⥰\":\"⥰\",\"⇛\":\"⇛\",\"ℛ\":\"ℛ\",\"↱\":\"↱\",\"⧴\":\"⧴\",\"Щ\":\"Щ\",\"Ш\":\"Ш\",\"Ь\":\"Ь\",\"Ś\":\"Ś\",\"⪼\":\"⪼\",\"Š\":\"Š\",\"Ş\":\"Ş\",\"Ŝ\":\"Ŝ\",\"С\":\"С\",\"𝔖\":\"𝔖\",\"↓\":\"↓\",\"←\":\"←\",\"→\":\"→\",\"↑\":\"↑\",\"Σ\":\"Σ\",\"∘\":\"∘\",\"𝕊\":\"𝕊\",\"√\":\"√\",\"□\":\"□\",\"⊓\":\"⊓\",\"⊏\":\"⊏\",\"⊑\":\"⊑\",\"⊐\":\"⊐\",\"⊒\":\"⊒\",\"⊔\":\"⊔\",\"𝒮\":\"𝒮\",\"⋆\":\"⋆\",\"⋐\":\"⋐\",\"⋐\":\"⋐\",\"⊆\":\"⊆\",\"≻\":\"≻\",\"⪰\":\"⪰\",\"≽\":\"≽\",\"≿\":\"≿\",\"∋\":\"∋\",\"∑\":\"∑\",\"⋑\":\"⋑\",\"⊃\":\"⊃\",\"⊇\":\"⊇\",\"⋑\":\"⋑\",\"Þ\":\"Þ\",\"Þ\":\"Þ\",\"™\":\"™\",\"Ћ\":\"Ћ\",\"Ц\":\"Ц\",\" \":\"\\t\",\"Τ\":\"Τ\",\"Ť\":\"Ť\",\"Ţ\":\"Ţ\",\"Т\":\"Т\",\"𝔗\":\"𝔗\",\"∴\":\"∴\",\"Θ\":\"Θ\",\"  \":\"  \",\" \":\" \",\"∼\":\"∼\",\"≃\":\"≃\",\"≅\":\"≅\",\"≈\":\"≈\",\"𝕋\":\"𝕋\",\"⃛\":\"⃛\",\"𝒯\":\"𝒯\",\"Ŧ\":\"Ŧ\",\"Ú\":\"Ú\",\"Ú\":\"Ú\",\"↟\":\"↟\",\"⥉\":\"⥉\",\"Ў\":\"Ў\",\"Ŭ\":\"Ŭ\",\"Û\":\"Û\",\"Û\":\"Û\",\"У\":\"У\",\"Ű\":\"Ű\",\"𝔘\":\"𝔘\",\"Ù\":\"Ù\",\"Ù\":\"Ù\",\"Ū\":\"Ū\",\"_\":\"_\",\"⏟\":\"⏟\",\"⎵\":\"⎵\",\"⏝\":\"⏝\",\"⋃\":\"⋃\",\"⊎\":\"⊎\",\"Ų\":\"Ų\",\"𝕌\":\"𝕌\",\"↑\":\"↑\",\"⤒\":\"⤒\",\"⇅\":\"⇅\",\"↕\":\"↕\",\"⥮\":\"⥮\",\"⊥\":\"⊥\",\"↥\":\"↥\",\"⇑\":\"⇑\",\"⇕\":\"⇕\",\"↖\":\"↖\",\"↗\":\"↗\",\"ϒ\":\"ϒ\",\"Υ\":\"Υ\",\"Ů\":\"Ů\",\"𝒰\":\"𝒰\",\"Ũ\":\"Ũ\",\"Ü\":\"Ü\",\"Ü\":\"Ü\",\"⊫\":\"⊫\",\"⫫\":\"⫫\",\"В\":\"В\",\"⊩\":\"⊩\",\"⫦\":\"⫦\",\"⋁\":\"⋁\",\"‖\":\"‖\",\"‖\":\"‖\",\"∣\":\"∣\",\"|\":\"|\",\"❘\":\"❘\",\"≀\":\"≀\",\" \":\" \",\"𝔙\":\"𝔙\",\"𝕍\":\"𝕍\",\"𝒱\":\"𝒱\",\"⊪\":\"⊪\",\"Ŵ\":\"Ŵ\",\"⋀\":\"⋀\",\"𝔚\":\"𝔚\",\"𝕎\":\"𝕎\",\"𝒲\":\"𝒲\",\"𝔛\":\"𝔛\",\"Ξ\":\"Ξ\",\"𝕏\":\"𝕏\",\"𝒳\":\"𝒳\",\"Я\":\"Я\",\"Ї\":\"Ї\",\"Ю\":\"Ю\",\"Ý\":\"Ý\",\"Ý\":\"Ý\",\"Ŷ\":\"Ŷ\",\"Ы\":\"Ы\",\"𝔜\":\"𝔜\",\"𝕐\":\"𝕐\",\"𝒴\":\"𝒴\",\"Ÿ\":\"Ÿ\",\"Ж\":\"Ж\",\"Ź\":\"Ź\",\"Ž\":\"Ž\",\"З\":\"З\",\"Ż\":\"Ż\",\"​\":\"​\",\"Ζ\":\"Ζ\",\"ℨ\":\"ℨ\",\"ℤ\":\"ℤ\",\"𝒵\":\"𝒵\",\"á\":\"á\",\"á\":\"á\",\"ă\":\"ă\",\"∾\":\"∾\",\"∾̳\":\"∾̳\",\"∿\":\"∿\",\"â\":\"â\",\"â\":\"â\",\"´\":\"´\",\"´\":\"´\",\"а\":\"а\",\"æ\":\"æ\",\"æ\":\"æ\",\"⁡\":\"⁡\",\"𝔞\":\"𝔞\",\"à\":\"à\",\"à\":\"à\",\"ℵ\":\"ℵ\",\"ℵ\":\"ℵ\",\"α\":\"α\",\"ā\":\"ā\",\"⨿\":\"⨿\",\"&\":\"&\",\"&\":\"&\",\"∧\":\"∧\",\"⩕\":\"⩕\",\"⩜\":\"⩜\",\"⩘\":\"⩘\",\"⩚\":\"⩚\",\"∠\":\"∠\",\"⦤\":\"⦤\",\"∠\":\"∠\",\"∡\":\"∡\",\"⦨\":\"⦨\",\"⦩\":\"⦩\",\"⦪\":\"⦪\",\"⦫\":\"⦫\",\"⦬\":\"⦬\",\"⦭\":\"⦭\",\"⦮\":\"⦮\",\"⦯\":\"⦯\",\"∟\":\"∟\",\"⊾\":\"⊾\",\"⦝\":\"⦝\",\"∢\":\"∢\",\"Å\":\"Å\",\"⍼\":\"⍼\",\"ą\":\"ą\",\"𝕒\":\"𝕒\",\"≈\":\"≈\",\"⩰\":\"⩰\",\"⩯\":\"⩯\",\"≊\":\"≊\",\"≋\":\"≋\",\"'\":\"'\",\"≈\":\"≈\",\"≊\":\"≊\",\"å\":\"å\",\"å\":\"å\",\"𝒶\":\"𝒶\",\"*\":\"*\",\"≈\":\"≈\",\"≍\":\"≍\",\"ã\":\"ã\",\"ã\":\"ã\",\"ä\":\"ä\",\"ä\":\"ä\",\"∳\":\"∳\",\"⨑\":\"⨑\",\"⫭\":\"⫭\",\"≌\":\"≌\",\"϶\":\"϶\",\"‵\":\"‵\",\"∽\":\"∽\",\"⋍\":\"⋍\",\"⊽\":\"⊽\",\"⌅\":\"⌅\",\"⌅\":\"⌅\",\"⎵\":\"⎵\",\"⎶\":\"⎶\",\"≌\":\"≌\",\"б\":\"б\",\"„\":\"„\",\"∵\":\"∵\",\"∵\":\"∵\",\"⦰\":\"⦰\",\"϶\":\"϶\",\"ℬ\":\"ℬ\",\"β\":\"β\",\"ℶ\":\"ℶ\",\"≬\":\"≬\",\"𝔟\":\"𝔟\",\"⋂\":\"⋂\",\"◯\":\"◯\",\"⋃\":\"⋃\",\"⨀\":\"⨀\",\"⨁\":\"⨁\",\"⨂\":\"⨂\",\"⨆\":\"⨆\",\"★\":\"★\",\"▽\":\"▽\",\"△\":\"△\",\"⨄\":\"⨄\",\"⋁\":\"⋁\",\"⋀\":\"⋀\",\"⤍\":\"⤍\",\"⧫\":\"⧫\",\"▪\":\"▪\",\"▴\":\"▴\",\"▾\":\"▾\",\"◂\":\"◂\",\"▸\":\"▸\",\"␣\":\"␣\",\"▒\":\"▒\",\"░\":\"░\",\"▓\":\"▓\",\"█\":\"█\",\"=⃥\":\"=⃥\",\"≡⃥\":\"≡⃥\",\"⌐\":\"⌐\",\"𝕓\":\"𝕓\",\"⊥\":\"⊥\",\"⊥\":\"⊥\",\"⋈\":\"⋈\",\"╗\":\"╗\",\"╔\":\"╔\",\"╖\":\"╖\",\"╓\":\"╓\",\"═\":\"═\",\"╦\":\"╦\",\"╩\":\"╩\",\"╤\":\"╤\",\"╧\":\"╧\",\"╝\":\"╝\",\"╚\":\"╚\",\"╜\":\"╜\",\"╙\":\"╙\",\"║\":\"║\",\"╬\":\"╬\",\"╣\":\"╣\",\"╠\":\"╠\",\"╫\":\"╫\",\"╢\":\"╢\",\"╟\":\"╟\",\"⧉\":\"⧉\",\"╕\":\"╕\",\"╒\":\"╒\",\"┐\":\"┐\",\"┌\":\"┌\",\"─\":\"─\",\"╥\":\"╥\",\"╨\":\"╨\",\"┬\":\"┬\",\"┴\":\"┴\",\"⊟\":\"⊟\",\"⊞\":\"⊞\",\"⊠\":\"⊠\",\"╛\":\"╛\",\"╘\":\"╘\",\"┘\":\"┘\",\"└\":\"└\",\"│\":\"│\",\"╪\":\"╪\",\"╡\":\"╡\",\"╞\":\"╞\",\"┼\":\"┼\",\"┤\":\"┤\",\"├\":\"├\",\"‵\":\"‵\",\"˘\":\"˘\",\"¦\":\"¦\",\"¦\":\"¦\",\"𝒷\":\"𝒷\",\"⁏\":\"⁏\",\"∽\":\"∽\",\"⋍\":\"⋍\",\"\\":\"\\\\\",\"⧅\":\"⧅\",\"⟈\":\"⟈\",\"•\":\"•\",\"•\":\"•\",\"≎\":\"≎\",\"⪮\":\"⪮\",\"≏\":\"≏\",\"≏\":\"≏\",\"ć\":\"ć\",\"∩\":\"∩\",\"⩄\":\"⩄\",\"⩉\":\"⩉\",\"⩋\":\"⩋\",\"⩇\":\"⩇\",\"⩀\":\"⩀\",\"∩︀\":\"∩︀\",\"⁁\":\"⁁\",\"ˇ\":\"ˇ\",\"⩍\":\"⩍\",\"č\":\"č\",\"ç\":\"ç\",\"ç\":\"ç\",\"ĉ\":\"ĉ\",\"⩌\":\"⩌\",\"⩐\":\"⩐\",\"ċ\":\"ċ\",\"¸\":\"¸\",\"¸\":\"¸\",\"⦲\":\"⦲\",\"¢\":\"¢\",\"¢\":\"¢\",\"·\":\"·\",\"𝔠\":\"𝔠\",\"ч\":\"ч\",\"✓\":\"✓\",\"✓\":\"✓\",\"χ\":\"χ\",\"○\":\"○\",\"⧃\":\"⧃\",\"ˆ\":\"ˆ\",\"≗\":\"≗\",\"↺\":\"↺\",\"↻\":\"↻\",\"®\":\"®\",\"Ⓢ\":\"Ⓢ\",\"⊛\":\"⊛\",\"⊚\":\"⊚\",\"⊝\":\"⊝\",\"≗\":\"≗\",\"⨐\":\"⨐\",\"⫯\":\"⫯\",\"⧂\":\"⧂\",\"♣\":\"♣\",\"♣\":\"♣\",\":\":\":\",\"≔\":\"≔\",\"≔\":\"≔\",\",\":\",\",\"@\":\"@\",\"∁\":\"∁\",\"∘\":\"∘\",\"∁\":\"∁\",\"ℂ\":\"ℂ\",\"≅\":\"≅\",\"⩭\":\"⩭\",\"∮\":\"∮\",\"𝕔\":\"𝕔\",\"∐\":\"∐\",\"©\":\"©\",\"©\":\"©\",\"℗\":\"℗\",\"↵\":\"↵\",\"✗\":\"✗\",\"𝒸\":\"𝒸\",\"⫏\":\"⫏\",\"⫑\":\"⫑\",\"⫐\":\"⫐\",\"⫒\":\"⫒\",\"⋯\":\"⋯\",\"⤸\":\"⤸\",\"⤵\":\"⤵\",\"⋞\":\"⋞\",\"⋟\":\"⋟\",\"↶\":\"↶\",\"⤽\":\"⤽\",\"∪\":\"∪\",\"⩈\":\"⩈\",\"⩆\":\"⩆\",\"⩊\":\"⩊\",\"⊍\":\"⊍\",\"⩅\":\"⩅\",\"∪︀\":\"∪︀\",\"↷\":\"↷\",\"⤼\":\"⤼\",\"⋞\":\"⋞\",\"⋟\":\"⋟\",\"⋎\":\"⋎\",\"⋏\":\"⋏\",\"¤\":\"¤\",\"¤\":\"¤\",\"↶\":\"↶\",\"↷\":\"↷\",\"⋎\":\"⋎\",\"⋏\":\"⋏\",\"∲\":\"∲\",\"∱\":\"∱\",\"⌭\":\"⌭\",\"⇓\":\"⇓\",\"⥥\":\"⥥\",\"†\":\"†\",\"ℸ\":\"ℸ\",\"↓\":\"↓\",\"‐\":\"‐\",\"⊣\":\"⊣\",\"⤏\":\"⤏\",\"˝\":\"˝\",\"ď\":\"ď\",\"д\":\"д\",\"ⅆ\":\"ⅆ\",\"‡\":\"‡\",\"⇊\":\"⇊\",\"⩷\":\"⩷\",\"°\":\"°\",\"°\":\"°\",\"δ\":\"δ\",\"⦱\":\"⦱\",\"⥿\":\"⥿\",\"𝔡\":\"𝔡\",\"⇃\":\"⇃\",\"⇂\":\"⇂\",\"⋄\":\"⋄\",\"⋄\":\"⋄\",\"♦\":\"♦\",\"♦\":\"♦\",\"¨\":\"¨\",\"ϝ\":\"ϝ\",\"⋲\":\"⋲\",\"÷\":\"÷\",\"÷\":\"÷\",\"÷\":\"÷\",\"⋇\":\"⋇\",\"⋇\":\"⋇\",\"ђ\":\"ђ\",\"⌞\":\"⌞\",\"⌍\":\"⌍\",\"$\":\"$\",\"𝕕\":\"𝕕\",\"˙\":\"˙\",\"≐\":\"≐\",\"≑\":\"≑\",\"∸\":\"∸\",\"∔\":\"∔\",\"⊡\":\"⊡\",\"⌆\":\"⌆\",\"↓\":\"↓\",\"⇊\":\"⇊\",\"⇃\":\"⇃\",\"⇂\":\"⇂\",\"⤐\":\"⤐\",\"⌟\":\"⌟\",\"⌌\":\"⌌\",\"𝒹\":\"𝒹\",\"ѕ\":\"ѕ\",\"⧶\":\"⧶\",\"đ\":\"đ\",\"⋱\":\"⋱\",\"▿\":\"▿\",\"▾\":\"▾\",\"⇵\":\"⇵\",\"⥯\":\"⥯\",\"⦦\":\"⦦\",\"џ\":\"џ\",\"⟿\":\"⟿\",\"⩷\":\"⩷\",\"≑\":\"≑\",\"é\":\"é\",\"é\":\"é\",\"⩮\":\"⩮\",\"ě\":\"ě\",\"≖\":\"≖\",\"ê\":\"ê\",\"ê\":\"ê\",\"≕\":\"≕\",\"э\":\"э\",\"ė\":\"ė\",\"ⅇ\":\"ⅇ\",\"≒\":\"≒\",\"𝔢\":\"𝔢\",\"⪚\":\"⪚\",\"è\":\"è\",\"è\":\"è\",\"⪖\":\"⪖\",\"⪘\":\"⪘\",\"⪙\":\"⪙\",\"⏧\":\"⏧\",\"ℓ\":\"ℓ\",\"⪕\":\"⪕\",\"⪗\":\"⪗\",\"ē\":\"ē\",\"∅\":\"∅\",\"∅\":\"∅\",\"∅\":\"∅\",\" \":\" \",\" \":\" \",\" \":\" \",\"ŋ\":\"ŋ\",\" \":\" \",\"ę\":\"ę\",\"𝕖\":\"𝕖\",\"⋕\":\"⋕\",\"⧣\":\"⧣\",\"⩱\":\"⩱\",\"ε\":\"ε\",\"ε\":\"ε\",\"ϵ\":\"ϵ\",\"≖\":\"≖\",\"≕\":\"≕\",\"≂\":\"≂\",\"⪖\":\"⪖\",\"⪕\":\"⪕\",\"=\":\"=\",\"≟\":\"≟\",\"≡\":\"≡\",\"⩸\":\"⩸\",\"⧥\":\"⧥\",\"≓\":\"≓\",\"⥱\":\"⥱\",\"ℯ\":\"ℯ\",\"≐\":\"≐\",\"≂\":\"≂\",\"η\":\"η\",\"ð\":\"ð\",\"ð\":\"ð\",\"ë\":\"ë\",\"ë\":\"ë\",\"€\":\"€\",\"!\":\"!\",\"∃\":\"∃\",\"ℰ\":\"ℰ\",\"ⅇ\":\"ⅇ\",\"≒\":\"≒\",\"ф\":\"ф\",\"♀\":\"♀\",\"ffi\":\"ffi\",\"ff\":\"ff\",\"ffl\":\"ffl\",\"𝔣\":\"𝔣\",\"fi\":\"fi\",\"fj\":\"fj\",\"♭\":\"♭\",\"fl\":\"fl\",\"▱\":\"▱\",\"ƒ\":\"ƒ\",\"𝕗\":\"𝕗\",\"∀\":\"∀\",\"⋔\":\"⋔\",\"⫙\":\"⫙\",\"⨍\":\"⨍\",\"½\":\"½\",\"½\":\"½\",\"⅓\":\"⅓\",\"¼\":\"¼\",\"¼\":\"¼\",\"⅕\":\"⅕\",\"⅙\":\"⅙\",\"⅛\":\"⅛\",\"⅔\":\"⅔\",\"⅖\":\"⅖\",\"¾\":\"¾\",\"¾\":\"¾\",\"⅗\":\"⅗\",\"⅜\":\"⅜\",\"⅘\":\"⅘\",\"⅚\":\"⅚\",\"⅝\":\"⅝\",\"⅞\":\"⅞\",\"⁄\":\"⁄\",\"⌢\":\"⌢\",\"𝒻\":\"𝒻\",\"≧\":\"≧\",\"⪌\":\"⪌\",\"ǵ\":\"ǵ\",\"γ\":\"γ\",\"ϝ\":\"ϝ\",\"⪆\":\"⪆\",\"ğ\":\"ğ\",\"ĝ\":\"ĝ\",\"г\":\"г\",\"ġ\":\"ġ\",\"≥\":\"≥\",\"⋛\":\"⋛\",\"≥\":\"≥\",\"≧\":\"≧\",\"⩾\":\"⩾\",\"⩾\":\"⩾\",\"⪩\":\"⪩\",\"⪀\":\"⪀\",\"⪂\":\"⪂\",\"⪄\":\"⪄\",\"⋛︀\":\"⋛︀\",\"⪔\":\"⪔\",\"𝔤\":\"𝔤\",\"≫\":\"≫\",\"⋙\":\"⋙\",\"ℷ\":\"ℷ\",\"ѓ\":\"ѓ\",\"≷\":\"≷\",\"⪒\":\"⪒\",\"⪥\":\"⪥\",\"⪤\":\"⪤\",\"≩\":\"≩\",\"⪊\":\"⪊\",\"⪊\":\"⪊\",\"⪈\":\"⪈\",\"⪈\":\"⪈\",\"≩\":\"≩\",\"⋧\":\"⋧\",\"𝕘\":\"𝕘\",\"`\":\"`\",\"ℊ\":\"ℊ\",\"≳\":\"≳\",\"⪎\":\"⪎\",\"⪐\":\"⪐\",\">\":\">\",\">\":\">\",\"⪧\":\"⪧\",\"⩺\":\"⩺\",\"⋗\":\"⋗\",\"⦕\":\"⦕\",\"⩼\":\"⩼\",\"⪆\":\"⪆\",\"⥸\":\"⥸\",\"⋗\":\"⋗\",\"⋛\":\"⋛\",\"⪌\":\"⪌\",\"≷\":\"≷\",\"≳\":\"≳\",\"≩︀\":\"≩︀\",\"≩︀\":\"≩︀\",\"⇔\":\"⇔\",\" \":\" \",\"½\":\"½\",\"ℋ\":\"ℋ\",\"ъ\":\"ъ\",\"↔\":\"↔\",\"⥈\":\"⥈\",\"↭\":\"↭\",\"ℏ\":\"ℏ\",\"ĥ\":\"ĥ\",\"♥\":\"♥\",\"♥\":\"♥\",\"…\":\"…\",\"⊹\":\"⊹\",\"𝔥\":\"𝔥\",\"⤥\":\"⤥\",\"⤦\":\"⤦\",\"⇿\":\"⇿\",\"∻\":\"∻\",\"↩\":\"↩\",\"↪\":\"↪\",\"𝕙\":\"𝕙\",\"―\":\"―\",\"𝒽\":\"𝒽\",\"ℏ\":\"ℏ\",\"ħ\":\"ħ\",\"⁃\":\"⁃\",\"‐\":\"‐\",\"í\":\"í\",\"í\":\"í\",\"⁣\":\"⁣\",\"î\":\"î\",\"î\":\"î\",\"и\":\"и\",\"е\":\"е\",\"¡\":\"¡\",\"¡\":\"¡\",\"⇔\":\"⇔\",\"𝔦\":\"𝔦\",\"ì\":\"ì\",\"ì\":\"ì\",\"ⅈ\":\"ⅈ\",\"⨌\":\"⨌\",\"∭\":\"∭\",\"⧜\":\"⧜\",\"℩\":\"℩\",\"ij\":\"ij\",\"ī\":\"ī\",\"ℑ\":\"ℑ\",\"ℐ\":\"ℐ\",\"ℑ\":\"ℑ\",\"ı\":\"ı\",\"⊷\":\"⊷\",\"Ƶ\":\"Ƶ\",\"∈\":\"∈\",\"℅\":\"℅\",\"∞\":\"∞\",\"⧝\":\"⧝\",\"ı\":\"ı\",\"∫\":\"∫\",\"⊺\":\"⊺\",\"ℤ\":\"ℤ\",\"⊺\":\"⊺\",\"⨗\":\"⨗\",\"⨼\":\"⨼\",\"ё\":\"ё\",\"į\":\"į\",\"𝕚\":\"𝕚\",\"ι\":\"ι\",\"⨼\":\"⨼\",\"¿\":\"¿\",\"¿\":\"¿\",\"𝒾\":\"𝒾\",\"∈\":\"∈\",\"⋹\":\"⋹\",\"⋵\":\"⋵\",\"⋴\":\"⋴\",\"⋳\":\"⋳\",\"∈\":\"∈\",\"⁢\":\"⁢\",\"ĩ\":\"ĩ\",\"і\":\"і\",\"ï\":\"ï\",\"ï\":\"ï\",\"ĵ\":\"ĵ\",\"й\":\"й\",\"𝔧\":\"𝔧\",\"ȷ\":\"ȷ\",\"𝕛\":\"𝕛\",\"𝒿\":\"𝒿\",\"ј\":\"ј\",\"є\":\"є\",\"κ\":\"κ\",\"ϰ\":\"ϰ\",\"ķ\":\"ķ\",\"к\":\"к\",\"𝔨\":\"𝔨\",\"ĸ\":\"ĸ\",\"х\":\"х\",\"ќ\":\"ќ\",\"𝕜\":\"𝕜\",\"𝓀\":\"𝓀\",\"⇚\":\"⇚\",\"⇐\":\"⇐\",\"⤛\":\"⤛\",\"⤎\":\"⤎\",\"≦\":\"≦\",\"⪋\":\"⪋\",\"⥢\":\"⥢\",\"ĺ\":\"ĺ\",\"⦴\":\"⦴\",\"ℒ\":\"ℒ\",\"λ\":\"λ\",\"⟨\":\"⟨\",\"⦑\":\"⦑\",\"⟨\":\"⟨\",\"⪅\":\"⪅\",\"«\":\"«\",\"«\":\"«\",\"←\":\"←\",\"⇤\":\"⇤\",\"⤟\":\"⤟\",\"⤝\":\"⤝\",\"↩\":\"↩\",\"↫\":\"↫\",\"⤹\":\"⤹\",\"⥳\":\"⥳\",\"↢\":\"↢\",\"⪫\":\"⪫\",\"⤙\":\"⤙\",\"⪭\":\"⪭\",\"⪭︀\":\"⪭︀\",\"⤌\":\"⤌\",\"❲\":\"❲\",\"{\":\"{\",\"[\":\"[\",\"⦋\":\"⦋\",\"⦏\":\"⦏\",\"⦍\":\"⦍\",\"ľ\":\"ľ\",\"ļ\":\"ļ\",\"⌈\":\"⌈\",\"{\":\"{\",\"л\":\"л\",\"⤶\":\"⤶\",\"“\":\"“\",\"„\":\"„\",\"⥧\":\"⥧\",\"⥋\":\"⥋\",\"↲\":\"↲\",\"≤\":\"≤\",\"←\":\"←\",\"↢\":\"↢\",\"↽\":\"↽\",\"↼\":\"↼\",\"⇇\":\"⇇\",\"↔\":\"↔\",\"⇆\":\"⇆\",\"⇋\":\"⇋\",\"↭\":\"↭\",\"⋋\":\"⋋\",\"⋚\":\"⋚\",\"≤\":\"≤\",\"≦\":\"≦\",\"⩽\":\"⩽\",\"⩽\":\"⩽\",\"⪨\":\"⪨\",\"⩿\":\"⩿\",\"⪁\":\"⪁\",\"⪃\":\"⪃\",\"⋚︀\":\"⋚︀\",\"⪓\":\"⪓\",\"⪅\":\"⪅\",\"⋖\":\"⋖\",\"⋚\":\"⋚\",\"⪋\":\"⪋\",\"≶\":\"≶\",\"≲\":\"≲\",\"⥼\":\"⥼\",\"⌊\":\"⌊\",\"𝔩\":\"𝔩\",\"≶\":\"≶\",\"⪑\":\"⪑\",\"↽\":\"↽\",\"↼\":\"↼\",\"⥪\":\"⥪\",\"▄\":\"▄\",\"љ\":\"љ\",\"≪\":\"≪\",\"⇇\":\"⇇\",\"⌞\":\"⌞\",\"⥫\":\"⥫\",\"◺\":\"◺\",\"ŀ\":\"ŀ\",\"⎰\":\"⎰\",\"⎰\":\"⎰\",\"≨\":\"≨\",\"⪉\":\"⪉\",\"⪉\":\"⪉\",\"⪇\":\"⪇\",\"⪇\":\"⪇\",\"≨\":\"≨\",\"⋦\":\"⋦\",\"⟬\":\"⟬\",\"⇽\":\"⇽\",\"⟦\":\"⟦\",\"⟵\":\"⟵\",\"⟷\":\"⟷\",\"⟼\":\"⟼\",\"⟶\":\"⟶\",\"↫\":\"↫\",\"↬\":\"↬\",\"⦅\":\"⦅\",\"𝕝\":\"𝕝\",\"⨭\":\"⨭\",\"⨴\":\"⨴\",\"∗\":\"∗\",\"_\":\"_\",\"◊\":\"◊\",\"◊\":\"◊\",\"⧫\":\"⧫\",\"(\":\"(\",\"⦓\":\"⦓\",\"⇆\":\"⇆\",\"⌟\":\"⌟\",\"⇋\":\"⇋\",\"⥭\":\"⥭\",\"‎\":\"‎\",\"⊿\":\"⊿\",\"‹\":\"‹\",\"𝓁\":\"𝓁\",\"↰\":\"↰\",\"≲\":\"≲\",\"⪍\":\"⪍\",\"⪏\":\"⪏\",\"[\":\"[\",\"‘\":\"‘\",\"‚\":\"‚\",\"ł\":\"ł\",\"<\":\"<\",\"<\":\"<\",\"⪦\":\"⪦\",\"⩹\":\"⩹\",\"⋖\":\"⋖\",\"⋋\":\"⋋\",\"⋉\":\"⋉\",\"⥶\":\"⥶\",\"⩻\":\"⩻\",\"⦖\":\"⦖\",\"◃\":\"◃\",\"⊴\":\"⊴\",\"◂\":\"◂\",\"⥊\":\"⥊\",\"⥦\":\"⥦\",\"≨︀\":\"≨︀\",\"≨︀\":\"≨︀\",\"∺\":\"∺\",\"¯\":\"¯\",\"¯\":\"¯\",\"♂\":\"♂\",\"✠\":\"✠\",\"✠\":\"✠\",\"↦\":\"↦\",\"↦\":\"↦\",\"↧\":\"↧\",\"↤\":\"↤\",\"↥\":\"↥\",\"▮\":\"▮\",\"⨩\":\"⨩\",\"м\":\"м\",\"—\":\"—\",\"∡\":\"∡\",\"𝔪\":\"𝔪\",\"℧\":\"℧\",\"µ\":\"µ\",\"µ\":\"µ\",\"∣\":\"∣\",\"*\":\"*\",\"⫰\":\"⫰\",\"·\":\"·\",\"·\":\"·\",\"−\":\"−\",\"⊟\":\"⊟\",\"∸\":\"∸\",\"⨪\":\"⨪\",\"⫛\":\"⫛\",\"…\":\"…\",\"∓\":\"∓\",\"⊧\":\"⊧\",\"𝕞\":\"𝕞\",\"∓\":\"∓\",\"𝓂\":\"𝓂\",\"∾\":\"∾\",\"μ\":\"μ\",\"⊸\":\"⊸\",\"⊸\":\"⊸\",\"⋙̸\":\"⋙̸\",\"≫⃒\":\"≫⃒\",\"≫̸\":\"≫̸\",\"⇍\":\"⇍\",\"⇎\":\"⇎\",\"⋘̸\":\"⋘̸\",\"≪⃒\":\"≪⃒\",\"≪̸\":\"≪̸\",\"⇏\":\"⇏\",\"⊯\":\"⊯\",\"⊮\":\"⊮\",\"∇\":\"∇\",\"ń\":\"ń\",\"∠⃒\":\"∠⃒\",\"≉\":\"≉\",\"⩰̸\":\"⩰̸\",\"≋̸\":\"≋̸\",\"ʼn\":\"ʼn\",\"≉\":\"≉\",\"♮\":\"♮\",\"♮\":\"♮\",\"ℕ\":\"ℕ\",\" \":\" \",\" \":\" \",\"≎̸\":\"≎̸\",\"≏̸\":\"≏̸\",\"⩃\":\"⩃\",\"ň\":\"ň\",\"ņ\":\"ņ\",\"≇\":\"≇\",\"⩭̸\":\"⩭̸\",\"⩂\":\"⩂\",\"н\":\"н\",\"–\":\"–\",\"≠\":\"≠\",\"⇗\":\"⇗\",\"⤤\":\"⤤\",\"↗\":\"↗\",\"↗\":\"↗\",\"≐̸\":\"≐̸\",\"≢\":\"≢\",\"⤨\":\"⤨\",\"≂̸\":\"≂̸\",\"∄\":\"∄\",\"∄\":\"∄\",\"𝔫\":\"𝔫\",\"≧̸\":\"≧̸\",\"≱\":\"≱\",\"≱\":\"≱\",\"≧̸\":\"≧̸\",\"⩾̸\":\"⩾̸\",\"⩾̸\":\"⩾̸\",\"≵\":\"≵\",\"≯\":\"≯\",\"≯\":\"≯\",\"⇎\":\"⇎\",\"↮\":\"↮\",\"⫲\":\"⫲\",\"∋\":\"∋\",\"⋼\":\"⋼\",\"⋺\":\"⋺\",\"∋\":\"∋\",\"њ\":\"њ\",\"⇍\":\"⇍\",\"≦̸\":\"≦̸\",\"↚\":\"↚\",\"‥\":\"‥\",\"≰\":\"≰\",\"↚\":\"↚\",\"↮\":\"↮\",\"≰\":\"≰\",\"≦̸\":\"≦̸\",\"⩽̸\":\"⩽̸\",\"⩽̸\":\"⩽̸\",\"≮\":\"≮\",\"≴\":\"≴\",\"≮\":\"≮\",\"⋪\":\"⋪\",\"⋬\":\"⋬\",\"∤\":\"∤\",\"𝕟\":\"𝕟\",\"¬\":\"¬\",\"¬\":\"¬\",\"∉\":\"∉\",\"⋹̸\":\"⋹̸\",\"⋵̸\":\"⋵̸\",\"∉\":\"∉\",\"⋷\":\"⋷\",\"⋶\":\"⋶\",\"∌\":\"∌\",\"∌\":\"∌\",\"⋾\":\"⋾\",\"⋽\":\"⋽\",\"∦\":\"∦\",\"∦\":\"∦\",\"⫽⃥\":\"⫽⃥\",\"∂̸\":\"∂̸\",\"⨔\":\"⨔\",\"⊀\":\"⊀\",\"⋠\":\"⋠\",\"⪯̸\":\"⪯̸\",\"⊀\":\"⊀\",\"⪯̸\":\"⪯̸\",\"⇏\":\"⇏\",\"↛\":\"↛\",\"⤳̸\":\"⤳̸\",\"↝̸\":\"↝̸\",\"↛\":\"↛\",\"⋫\":\"⋫\",\"⋭\":\"⋭\",\"⊁\":\"⊁\",\"⋡\":\"⋡\",\"⪰̸\":\"⪰̸\",\"𝓃\":\"𝓃\",\"∤\":\"∤\",\"∦\":\"∦\",\"≁\":\"≁\",\"≄\":\"≄\",\"≄\":\"≄\",\"∤\":\"∤\",\"∦\":\"∦\",\"⋢\":\"⋢\",\"⋣\":\"⋣\",\"⊄\":\"⊄\",\"⫅̸\":\"⫅̸\",\"⊈\":\"⊈\",\"⊂⃒\":\"⊂⃒\",\"⊈\":\"⊈\",\"⫅̸\":\"⫅̸\",\"⊁\":\"⊁\",\"⪰̸\":\"⪰̸\",\"⊅\":\"⊅\",\"⫆̸\":\"⫆̸\",\"⊉\":\"⊉\",\"⊃⃒\":\"⊃⃒\",\"⊉\":\"⊉\",\"⫆̸\":\"⫆̸\",\"≹\":\"≹\",\"ñ\":\"ñ\",\"ñ\":\"ñ\",\"≸\":\"≸\",\"⋪\":\"⋪\",\"⋬\":\"⋬\",\"⋫\":\"⋫\",\"⋭\":\"⋭\",\"ν\":\"ν\",\"#\":\"#\",\"№\":\"№\",\" \":\" \",\"⊭\":\"⊭\",\"⤄\":\"⤄\",\"≍⃒\":\"≍⃒\",\"⊬\":\"⊬\",\"≥⃒\":\"≥⃒\",\">⃒\":\">⃒\",\"⧞\":\"⧞\",\"⤂\":\"⤂\",\"≤⃒\":\"≤⃒\",\"<⃒\":\"<⃒\",\"⊴⃒\":\"⊴⃒\",\"⤃\":\"⤃\",\"⊵⃒\":\"⊵⃒\",\"∼⃒\":\"∼⃒\",\"⇖\":\"⇖\",\"⤣\":\"⤣\",\"↖\":\"↖\",\"↖\":\"↖\",\"⤧\":\"⤧\",\"Ⓢ\":\"Ⓢ\",\"ó\":\"ó\",\"ó\":\"ó\",\"⊛\":\"⊛\",\"⊚\":\"⊚\",\"ô\":\"ô\",\"ô\":\"ô\",\"о\":\"о\",\"⊝\":\"⊝\",\"ő\":\"ő\",\"⨸\":\"⨸\",\"⊙\":\"⊙\",\"⦼\":\"⦼\",\"œ\":\"œ\",\"⦿\":\"⦿\",\"𝔬\":\"𝔬\",\"˛\":\"˛\",\"ò\":\"ò\",\"ò\":\"ò\",\"⧁\":\"⧁\",\"⦵\":\"⦵\",\"Ω\":\"Ω\",\"∮\":\"∮\",\"↺\":\"↺\",\"⦾\":\"⦾\",\"⦻\":\"⦻\",\"‾\":\"‾\",\"⧀\":\"⧀\",\"ō\":\"ō\",\"ω\":\"ω\",\"ο\":\"ο\",\"⦶\":\"⦶\",\"⊖\":\"⊖\",\"𝕠\":\"𝕠\",\"⦷\":\"⦷\",\"⦹\":\"⦹\",\"⊕\":\"⊕\",\"∨\":\"∨\",\"↻\":\"↻\",\"⩝\":\"⩝\",\"ℴ\":\"ℴ\",\"ℴ\":\"ℴ\",\"ª\":\"ª\",\"ª\":\"ª\",\"º\":\"º\",\"º\":\"º\",\"⊶\":\"⊶\",\"⩖\":\"⩖\",\"⩗\":\"⩗\",\"⩛\":\"⩛\",\"ℴ\":\"ℴ\",\"ø\":\"ø\",\"ø\":\"ø\",\"⊘\":\"⊘\",\"õ\":\"õ\",\"õ\":\"õ\",\"⊗\":\"⊗\",\"⨶\":\"⨶\",\"ö\":\"ö\",\"ö\":\"ö\",\"⌽\":\"⌽\",\"∥\":\"∥\",\"¶\":\"¶\",\"¶\":\"¶\",\"∥\":\"∥\",\"⫳\":\"⫳\",\"⫽\":\"⫽\",\"∂\":\"∂\",\"п\":\"п\",\"%\":\"%\",\".\":\".\",\"‰\":\"‰\",\"⊥\":\"⊥\",\"‱\":\"‱\",\"𝔭\":\"𝔭\",\"φ\":\"φ\",\"ϕ\":\"ϕ\",\"ℳ\":\"ℳ\",\"☎\":\"☎\",\"π\":\"π\",\"⋔\":\"⋔\",\"ϖ\":\"ϖ\",\"ℏ\":\"ℏ\",\"ℎ\":\"ℎ\",\"ℏ\":\"ℏ\",\"+\":\"+\",\"⨣\":\"⨣\",\"⊞\":\"⊞\",\"⨢\":\"⨢\",\"∔\":\"∔\",\"⨥\":\"⨥\",\"⩲\":\"⩲\",\"±\":\"±\",\"±\":\"±\",\"⨦\":\"⨦\",\"⨧\":\"⨧\",\"±\":\"±\",\"⨕\":\"⨕\",\"𝕡\":\"𝕡\",\"£\":\"£\",\"£\":\"£\",\"≺\":\"≺\",\"⪳\":\"⪳\",\"⪷\":\"⪷\",\"≼\":\"≼\",\"⪯\":\"⪯\",\"≺\":\"≺\",\"⪷\":\"⪷\",\"≼\":\"≼\",\"⪯\":\"⪯\",\"⪹\":\"⪹\",\"⪵\":\"⪵\",\"⋨\":\"⋨\",\"≾\":\"≾\",\"′\":\"′\",\"ℙ\":\"ℙ\",\"⪵\":\"⪵\",\"⪹\":\"⪹\",\"⋨\":\"⋨\",\"∏\":\"∏\",\"⌮\":\"⌮\",\"⌒\":\"⌒\",\"⌓\":\"⌓\",\"∝\":\"∝\",\"∝\":\"∝\",\"≾\":\"≾\",\"⊰\":\"⊰\",\"𝓅\":\"𝓅\",\"ψ\":\"ψ\",\" \":\" \",\"𝔮\":\"𝔮\",\"⨌\":\"⨌\",\"𝕢\":\"𝕢\",\"⁗\":\"⁗\",\"𝓆\":\"𝓆\",\"ℍ\":\"ℍ\",\"⨖\":\"⨖\",\"?\":\"?\",\"≟\":\"≟\",\""\":'\"',\""\":'\"',\"⇛\":\"⇛\",\"⇒\":\"⇒\",\"⤜\":\"⤜\",\"⤏\":\"⤏\",\"⥤\":\"⥤\",\"∽̱\":\"∽̱\",\"ŕ\":\"ŕ\",\"√\":\"√\",\"⦳\":\"⦳\",\"⟩\":\"⟩\",\"⦒\":\"⦒\",\"⦥\":\"⦥\",\"⟩\":\"⟩\",\"»\":\"»\",\"»\":\"»\",\"→\":\"→\",\"⥵\":\"⥵\",\"⇥\":\"⇥\",\"⤠\":\"⤠\",\"⤳\":\"⤳\",\"⤞\":\"⤞\",\"↪\":\"↪\",\"↬\":\"↬\",\"⥅\":\"⥅\",\"⥴\":\"⥴\",\"↣\":\"↣\",\"↝\":\"↝\",\"⤚\":\"⤚\",\"∶\":\"∶\",\"ℚ\":\"ℚ\",\"⤍\":\"⤍\",\"❳\":\"❳\",\"}\":\"}\",\"]\":\"]\",\"⦌\":\"⦌\",\"⦎\":\"⦎\",\"⦐\":\"⦐\",\"ř\":\"ř\",\"ŗ\":\"ŗ\",\"⌉\":\"⌉\",\"}\":\"}\",\"р\":\"р\",\"⤷\":\"⤷\",\"⥩\":\"⥩\",\"”\":\"”\",\"”\":\"”\",\"↳\":\"↳\",\"ℜ\":\"ℜ\",\"ℛ\":\"ℛ\",\"ℜ\":\"ℜ\",\"ℝ\":\"ℝ\",\"▭\":\"▭\",\"®\":\"®\",\"®\":\"®\",\"⥽\":\"⥽\",\"⌋\":\"⌋\",\"𝔯\":\"𝔯\",\"⇁\":\"⇁\",\"⇀\":\"⇀\",\"⥬\":\"⥬\",\"ρ\":\"ρ\",\"ϱ\":\"ϱ\",\"→\":\"→\",\"↣\":\"↣\",\"⇁\":\"⇁\",\"⇀\":\"⇀\",\"⇄\":\"⇄\",\"⇌\":\"⇌\",\"⇉\":\"⇉\",\"↝\":\"↝\",\"⋌\":\"⋌\",\"˚\":\"˚\",\"≓\":\"≓\",\"⇄\":\"⇄\",\"⇌\":\"⇌\",\"‏\":\"‏\",\"⎱\":\"⎱\",\"⎱\":\"⎱\",\"⫮\":\"⫮\",\"⟭\":\"⟭\",\"⇾\":\"⇾\",\"⟧\":\"⟧\",\"⦆\":\"⦆\",\"𝕣\":\"𝕣\",\"⨮\":\"⨮\",\"⨵\":\"⨵\",\")\":\")\",\"⦔\":\"⦔\",\"⨒\":\"⨒\",\"⇉\":\"⇉\",\"›\":\"›\",\"𝓇\":\"𝓇\",\"↱\":\"↱\",\"]\":\"]\",\"’\":\"’\",\"’\":\"’\",\"⋌\":\"⋌\",\"⋊\":\"⋊\",\"▹\":\"▹\",\"⊵\":\"⊵\",\"▸\":\"▸\",\"⧎\":\"⧎\",\"⥨\":\"⥨\",\"℞\":\"℞\",\"ś\":\"ś\",\"‚\":\"‚\",\"≻\":\"≻\",\"⪴\":\"⪴\",\"⪸\":\"⪸\",\"š\":\"š\",\"≽\":\"≽\",\"⪰\":\"⪰\",\"ş\":\"ş\",\"ŝ\":\"ŝ\",\"⪶\":\"⪶\",\"⪺\":\"⪺\",\"⋩\":\"⋩\",\"⨓\":\"⨓\",\"≿\":\"≿\",\"с\":\"с\",\"⋅\":\"⋅\",\"⊡\":\"⊡\",\"⩦\":\"⩦\",\"⇘\":\"⇘\",\"⤥\":\"⤥\",\"↘\":\"↘\",\"↘\":\"↘\",\"§\":\"§\",\"§\":\"§\",\";\":\";\",\"⤩\":\"⤩\",\"∖\":\"∖\",\"∖\":\"∖\",\"✶\":\"✶\",\"𝔰\":\"𝔰\",\"⌢\":\"⌢\",\"♯\":\"♯\",\"щ\":\"щ\",\"ш\":\"ш\",\"∣\":\"∣\",\"∥\":\"∥\",\"­\":\"­\",\"­\":\"­\",\"σ\":\"σ\",\"ς\":\"ς\",\"ς\":\"ς\",\"∼\":\"∼\",\"⩪\":\"⩪\",\"≃\":\"≃\",\"≃\":\"≃\",\"⪞\":\"⪞\",\"⪠\":\"⪠\",\"⪝\":\"⪝\",\"⪟\":\"⪟\",\"≆\":\"≆\",\"⨤\":\"⨤\",\"⥲\":\"⥲\",\"←\":\"←\",\"∖\":\"∖\",\"⨳\":\"⨳\",\"⧤\":\"⧤\",\"∣\":\"∣\",\"⌣\":\"⌣\",\"⪪\":\"⪪\",\"⪬\":\"⪬\",\"⪬︀\":\"⪬︀\",\"ь\":\"ь\",\"/\":\"/\",\"⧄\":\"⧄\",\"⌿\":\"⌿\",\"𝕤\":\"𝕤\",\"♠\":\"♠\",\"♠\":\"♠\",\"∥\":\"∥\",\"⊓\":\"⊓\",\"⊓︀\":\"⊓︀\",\"⊔\":\"⊔\",\"⊔︀\":\"⊔︀\",\"⊏\":\"⊏\",\"⊑\":\"⊑\",\"⊏\":\"⊏\",\"⊑\":\"⊑\",\"⊐\":\"⊐\",\"⊒\":\"⊒\",\"⊐\":\"⊐\",\"⊒\":\"⊒\",\"□\":\"□\",\"□\":\"□\",\"▪\":\"▪\",\"▪\":\"▪\",\"→\":\"→\",\"𝓈\":\"𝓈\",\"∖\":\"∖\",\"⌣\":\"⌣\",\"⋆\":\"⋆\",\"☆\":\"☆\",\"★\":\"★\",\"ϵ\":\"ϵ\",\"ϕ\":\"ϕ\",\"¯\":\"¯\",\"⊂\":\"⊂\",\"⫅\":\"⫅\",\"⪽\":\"⪽\",\"⊆\":\"⊆\",\"⫃\":\"⫃\",\"⫁\":\"⫁\",\"⫋\":\"⫋\",\"⊊\":\"⊊\",\"⪿\":\"⪿\",\"⥹\":\"⥹\",\"⊂\":\"⊂\",\"⊆\":\"⊆\",\"⫅\":\"⫅\",\"⊊\":\"⊊\",\"⫋\":\"⫋\",\"⫇\":\"⫇\",\"⫕\":\"⫕\",\"⫓\":\"⫓\",\"≻\":\"≻\",\"⪸\":\"⪸\",\"≽\":\"≽\",\"⪰\":\"⪰\",\"⪺\":\"⪺\",\"⪶\":\"⪶\",\"⋩\":\"⋩\",\"≿\":\"≿\",\"∑\":\"∑\",\"♪\":\"♪\",\"¹\":\"¹\",\"¹\":\"¹\",\"²\":\"²\",\"²\":\"²\",\"³\":\"³\",\"³\":\"³\",\"⊃\":\"⊃\",\"⫆\":\"⫆\",\"⪾\":\"⪾\",\"⫘\":\"⫘\",\"⊇\":\"⊇\",\"⫄\":\"⫄\",\"⟉\":\"⟉\",\"⫗\":\"⫗\",\"⥻\":\"⥻\",\"⫂\":\"⫂\",\"⫌\":\"⫌\",\"⊋\":\"⊋\",\"⫀\":\"⫀\",\"⊃\":\"⊃\",\"⊇\":\"⊇\",\"⫆\":\"⫆\",\"⊋\":\"⊋\",\"⫌\":\"⫌\",\"⫈\":\"⫈\",\"⫔\":\"⫔\",\"⫖\":\"⫖\",\"⇙\":\"⇙\",\"⤦\":\"⤦\",\"↙\":\"↙\",\"↙\":\"↙\",\"⤪\":\"⤪\",\"ß\":\"ß\",\"ß\":\"ß\",\"⌖\":\"⌖\",\"τ\":\"τ\",\"⎴\":\"⎴\",\"ť\":\"ť\",\"ţ\":\"ţ\",\"т\":\"т\",\"⃛\":\"⃛\",\"⌕\":\"⌕\",\"𝔱\":\"𝔱\",\"∴\":\"∴\",\"∴\":\"∴\",\"θ\":\"θ\",\"ϑ\":\"ϑ\",\"ϑ\":\"ϑ\",\"≈\":\"≈\",\"∼\":\"∼\",\" \":\" \",\"≈\":\"≈\",\"∼\":\"∼\",\"þ\":\"þ\",\"þ\":\"þ\",\"˜\":\"˜\",\"×\":\"×\",\"×\":\"×\",\"⊠\":\"⊠\",\"⨱\":\"⨱\",\"⨰\":\"⨰\",\"∭\":\"∭\",\"⤨\":\"⤨\",\"⊤\":\"⊤\",\"⌶\":\"⌶\",\"⫱\":\"⫱\",\"𝕥\":\"𝕥\",\"⫚\":\"⫚\",\"⤩\":\"⤩\",\"‴\":\"‴\",\"™\":\"™\",\"▵\":\"▵\",\"▿\":\"▿\",\"◃\":\"◃\",\"⊴\":\"⊴\",\"≜\":\"≜\",\"▹\":\"▹\",\"⊵\":\"⊵\",\"◬\":\"◬\",\"≜\":\"≜\",\"⨺\":\"⨺\",\"⨹\":\"⨹\",\"⧍\":\"⧍\",\"⨻\":\"⨻\",\"⏢\":\"⏢\",\"𝓉\":\"𝓉\",\"ц\":\"ц\",\"ћ\":\"ћ\",\"ŧ\":\"ŧ\",\"≬\":\"≬\",\"↞\":\"↞\",\"↠\":\"↠\",\"⇑\":\"⇑\",\"⥣\":\"⥣\",\"ú\":\"ú\",\"ú\":\"ú\",\"↑\":\"↑\",\"ў\":\"ў\",\"ŭ\":\"ŭ\",\"û\":\"û\",\"û\":\"û\",\"у\":\"у\",\"⇅\":\"⇅\",\"ű\":\"ű\",\"⥮\":\"⥮\",\"⥾\":\"⥾\",\"𝔲\":\"𝔲\",\"ù\":\"ù\",\"ù\":\"ù\",\"↿\":\"↿\",\"↾\":\"↾\",\"▀\":\"▀\",\"⌜\":\"⌜\",\"⌜\":\"⌜\",\"⌏\":\"⌏\",\"◸\":\"◸\",\"ū\":\"ū\",\"¨\":\"¨\",\"¨\":\"¨\",\"ų\":\"ų\",\"𝕦\":\"𝕦\",\"↑\":\"↑\",\"↕\":\"↕\",\"↿\":\"↿\",\"↾\":\"↾\",\"⊎\":\"⊎\",\"υ\":\"υ\",\"ϒ\":\"ϒ\",\"υ\":\"υ\",\"⇈\":\"⇈\",\"⌝\":\"⌝\",\"⌝\":\"⌝\",\"⌎\":\"⌎\",\"ů\":\"ů\",\"◹\":\"◹\",\"𝓊\":\"𝓊\",\"⋰\":\"⋰\",\"ũ\":\"ũ\",\"▵\":\"▵\",\"▴\":\"▴\",\"⇈\":\"⇈\",\"ü\":\"ü\",\"ü\":\"ü\",\"⦧\":\"⦧\",\"⇕\":\"⇕\",\"⫨\":\"⫨\",\"⫩\":\"⫩\",\"⊨\":\"⊨\",\"⦜\":\"⦜\",\"ϵ\":\"ϵ\",\"ϰ\":\"ϰ\",\"∅\":\"∅\",\"ϕ\":\"ϕ\",\"ϖ\":\"ϖ\",\"∝\":\"∝\",\"↕\":\"↕\",\"ϱ\":\"ϱ\",\"ς\":\"ς\",\"⊊︀\":\"⊊︀\",\"⫋︀\":\"⫋︀\",\"⊋︀\":\"⊋︀\",\"⫌︀\":\"⫌︀\",\"ϑ\":\"ϑ\",\"⊲\":\"⊲\",\"⊳\":\"⊳\",\"в\":\"в\",\"⊢\":\"⊢\",\"∨\":\"∨\",\"⊻\":\"⊻\",\"≚\":\"≚\",\"⋮\":\"⋮\",\"|\":\"|\",\"|\":\"|\",\"𝔳\":\"𝔳\",\"⊲\":\"⊲\",\"⊂⃒\":\"⊂⃒\",\"⊃⃒\":\"⊃⃒\",\"𝕧\":\"𝕧\",\"∝\":\"∝\",\"⊳\":\"⊳\",\"𝓋\":\"𝓋\",\"⫋︀\":\"⫋︀\",\"⊊︀\":\"⊊︀\",\"⫌︀\":\"⫌︀\",\"⊋︀\":\"⊋︀\",\"⦚\":\"⦚\",\"ŵ\":\"ŵ\",\"⩟\":\"⩟\",\"∧\":\"∧\",\"≙\":\"≙\",\"℘\":\"℘\",\"𝔴\":\"𝔴\",\"𝕨\":\"𝕨\",\"℘\":\"℘\",\"≀\":\"≀\",\"≀\":\"≀\",\"𝓌\":\"𝓌\",\"⋂\":\"⋂\",\"◯\":\"◯\",\"⋃\":\"⋃\",\"▽\":\"▽\",\"𝔵\":\"𝔵\",\"⟺\":\"⟺\",\"⟷\":\"⟷\",\"ξ\":\"ξ\",\"⟸\":\"⟸\",\"⟵\":\"⟵\",\"⟼\":\"⟼\",\"⋻\":\"⋻\",\"⨀\":\"⨀\",\"𝕩\":\"𝕩\",\"⨁\":\"⨁\",\"⨂\":\"⨂\",\"⟹\":\"⟹\",\"⟶\":\"⟶\",\"𝓍\":\"𝓍\",\"⨆\":\"⨆\",\"⨄\":\"⨄\",\"△\":\"△\",\"⋁\":\"⋁\",\"⋀\":\"⋀\",\"ý\":\"ý\",\"ý\":\"ý\",\"я\":\"я\",\"ŷ\":\"ŷ\",\"ы\":\"ы\",\"¥\":\"¥\",\"¥\":\"¥\",\"𝔶\":\"𝔶\",\"ї\":\"ї\",\"𝕪\":\"𝕪\",\"𝓎\":\"𝓎\",\"ю\":\"ю\",\"ÿ\":\"ÿ\",\"ÿ\":\"ÿ\",\"ź\":\"ź\",\"ž\":\"ž\",\"з\":\"з\",\"ż\":\"ż\",\"ℨ\":\"ℨ\",\"ζ\":\"ζ\",\"𝔷\":\"𝔷\",\"ж\":\"ж\",\"⇝\":\"⇝\",\"𝕫\":\"𝕫\",\"𝓏\":\"𝓏\",\"‍\":\"‍\",\"‌\":\"‌\"},characters:{\"Æ\":\"Æ\",\"&\":\"&\",\"Á\":\"Á\",\"Ă\":\"Ă\",\"Â\":\"Â\",\"А\":\"А\",\"𝔄\":\"𝔄\",\"À\":\"À\",\"Α\":\"Α\",\"Ā\":\"Ā\",\"⩓\":\"⩓\",\"Ą\":\"Ą\",\"𝔸\":\"𝔸\",\"⁡\":\"⁡\",\"Å\":\"Å\",\"𝒜\":\"𝒜\",\"≔\":\"≔\",\"Ã\":\"Ã\",\"Ä\":\"Ä\",\"∖\":\"∖\",\"⫧\":\"⫧\",\"⌆\":\"⌆\",\"Б\":\"Б\",\"∵\":\"∵\",\"ℬ\":\"ℬ\",\"Β\":\"Β\",\"𝔅\":\"𝔅\",\"𝔹\":\"𝔹\",\"˘\":\"˘\",\"≎\":\"≎\",\"Ч\":\"Ч\",\"©\":\"©\",\"Ć\":\"Ć\",\"⋒\":\"⋒\",\"ⅅ\":\"ⅅ\",\"ℭ\":\"ℭ\",\"Č\":\"Č\",\"Ç\":\"Ç\",\"Ĉ\":\"Ĉ\",\"∰\":\"∰\",\"Ċ\":\"Ċ\",\"¸\":\"¸\",\"·\":\"·\",\"Χ\":\"Χ\",\"⊙\":\"⊙\",\"⊖\":\"⊖\",\"⊕\":\"⊕\",\"⊗\":\"⊗\",\"∲\":\"∲\",\"”\":\"”\",\"’\":\"’\",\"∷\":\"∷\",\"⩴\":\"⩴\",\"≡\":\"≡\",\"∯\":\"∯\",\"∮\":\"∮\",\"ℂ\":\"ℂ\",\"∐\":\"∐\",\"∳\":\"∳\",\"⨯\":\"⨯\",\"𝒞\":\"𝒞\",\"⋓\":\"⋓\",\"≍\":\"≍\",\"⤑\":\"⤑\",\"Ђ\":\"Ђ\",\"Ѕ\":\"Ѕ\",\"Џ\":\"Џ\",\"‡\":\"‡\",\"↡\":\"↡\",\"⫤\":\"⫤\",\"Ď\":\"Ď\",\"Д\":\"Д\",\"∇\":\"∇\",\"Δ\":\"Δ\",\"𝔇\":\"𝔇\",\"´\":\"´\",\"˙\":\"˙\",\"˝\":\"˝\",\"`\":\"`\",\"˜\":\"˜\",\"⋄\":\"⋄\",\"ⅆ\":\"ⅆ\",\"𝔻\":\"𝔻\",\"¨\":\"¨\",\"⃜\":\"⃜\",\"≐\":\"≐\",\"⇓\":\"⇓\",\"⇐\":\"⇐\",\"⇔\":\"⇔\",\"⟸\":\"⟸\",\"⟺\":\"⟺\",\"⟹\":\"⟹\",\"⇒\":\"⇒\",\"⊨\":\"⊨\",\"⇑\":\"⇑\",\"⇕\":\"⇕\",\"∥\":\"∥\",\"↓\":\"↓\",\"⤓\":\"⤓\",\"⇵\":\"⇵\",\"̑\":\"̑\",\"⥐\":\"⥐\",\"⥞\":\"⥞\",\"↽\":\"↽\",\"⥖\":\"⥖\",\"⥟\":\"⥟\",\"⇁\":\"⇁\",\"⥗\":\"⥗\",\"⊤\":\"⊤\",\"↧\":\"↧\",\"𝒟\":\"𝒟\",\"Đ\":\"Đ\",\"Ŋ\":\"Ŋ\",\"Ð\":\"Ð\",\"É\":\"É\",\"Ě\":\"Ě\",\"Ê\":\"Ê\",\"Э\":\"Э\",\"Ė\":\"Ė\",\"𝔈\":\"𝔈\",\"È\":\"È\",\"∈\":\"∈\",\"Ē\":\"Ē\",\"◻\":\"◻\",\"▫\":\"▫\",\"Ę\":\"Ę\",\"𝔼\":\"𝔼\",\"Ε\":\"Ε\",\"⩵\":\"⩵\",\"≂\":\"≂\",\"⇌\":\"⇌\",\"ℰ\":\"ℰ\",\"⩳\":\"⩳\",\"Η\":\"Η\",\"Ë\":\"Ë\",\"∃\":\"∃\",\"ⅇ\":\"ⅇ\",\"Ф\":\"Ф\",\"𝔉\":\"𝔉\",\"◼\":\"◼\",\"▪\":\"▪\",\"𝔽\":\"𝔽\",\"∀\":\"∀\",\"ℱ\":\"ℱ\",\"Ѓ\":\"Ѓ\",\">\":\">\",\"Γ\":\"Γ\",\"Ϝ\":\"Ϝ\",\"Ğ\":\"Ğ\",\"Ģ\":\"Ģ\",\"Ĝ\":\"Ĝ\",\"Г\":\"Г\",\"Ġ\":\"Ġ\",\"𝔊\":\"𝔊\",\"⋙\":\"⋙\",\"𝔾\":\"𝔾\",\"≥\":\"≥\",\"⋛\":\"⋛\",\"≧\":\"≧\",\"⪢\":\"⪢\",\"≷\":\"≷\",\"⩾\":\"⩾\",\"≳\":\"≳\",\"𝒢\":\"𝒢\",\"≫\":\"≫\",\"Ъ\":\"Ъ\",\"ˇ\":\"ˇ\",\"^\":\"^\",\"Ĥ\":\"Ĥ\",\"ℌ\":\"ℌ\",\"ℋ\":\"ℋ\",\"ℍ\":\"ℍ\",\"─\":\"─\",\"Ħ\":\"Ħ\",\"≏\":\"≏\",\"Е\":\"Е\",\"IJ\":\"IJ\",\"Ё\":\"Ё\",\"Í\":\"Í\",\"Î\":\"Î\",\"И\":\"И\",\"İ\":\"İ\",\"ℑ\":\"ℑ\",\"Ì\":\"Ì\",\"Ī\":\"Ī\",\"ⅈ\":\"ⅈ\",\"∬\":\"∬\",\"∫\":\"∫\",\"⋂\":\"⋂\",\"⁣\":\"⁣\",\"⁢\":\"⁢\",\"Į\":\"Į\",\"𝕀\":\"𝕀\",\"Ι\":\"Ι\",\"ℐ\":\"ℐ\",\"Ĩ\":\"Ĩ\",\"І\":\"І\",\"Ï\":\"Ï\",\"Ĵ\":\"Ĵ\",\"Й\":\"Й\",\"𝔍\":\"𝔍\",\"𝕁\":\"𝕁\",\"𝒥\":\"𝒥\",\"Ј\":\"Ј\",\"Є\":\"Є\",\"Х\":\"Х\",\"Ќ\":\"Ќ\",\"Κ\":\"Κ\",\"Ķ\":\"Ķ\",\"К\":\"К\",\"𝔎\":\"𝔎\",\"𝕂\":\"𝕂\",\"𝒦\":\"𝒦\",\"Љ\":\"Љ\",\"<\":\"<\",\"Ĺ\":\"Ĺ\",\"Λ\":\"Λ\",\"⟪\":\"⟪\",\"ℒ\":\"ℒ\",\"↞\":\"↞\",\"Ľ\":\"Ľ\",\"Ļ\":\"Ļ\",\"Л\":\"Л\",\"⟨\":\"⟨\",\"←\":\"←\",\"⇤\":\"⇤\",\"⇆\":\"⇆\",\"⌈\":\"⌈\",\"⟦\":\"⟦\",\"⥡\":\"⥡\",\"⇃\":\"⇃\",\"⥙\":\"⥙\",\"⌊\":\"⌊\",\"↔\":\"↔\",\"⥎\":\"⥎\",\"⊣\":\"⊣\",\"↤\":\"↤\",\"⥚\":\"⥚\",\"⊲\":\"⊲\",\"⧏\":\"⧏\",\"⊴\":\"⊴\",\"⥑\":\"⥑\",\"⥠\":\"⥠\",\"↿\":\"↿\",\"⥘\":\"⥘\",\"↼\":\"↼\",\"⥒\":\"⥒\",\"⋚\":\"⋚\",\"≦\":\"≦\",\"≶\":\"≶\",\"⪡\":\"⪡\",\"⩽\":\"⩽\",\"≲\":\"≲\",\"𝔏\":\"𝔏\",\"⋘\":\"⋘\",\"⇚\":\"⇚\",\"Ŀ\":\"Ŀ\",\"⟵\":\"⟵\",\"⟷\":\"⟷\",\"⟶\":\"⟶\",\"𝕃\":\"𝕃\",\"↙\":\"↙\",\"↘\":\"↘\",\"↰\":\"↰\",\"Ł\":\"Ł\",\"≪\":\"≪\",\"⤅\":\"⤅\",\"М\":\"М\",\" \":\" \",\"ℳ\":\"ℳ\",\"𝔐\":\"𝔐\",\"∓\":\"∓\",\"𝕄\":\"𝕄\",\"Μ\":\"Μ\",\"Њ\":\"Њ\",\"Ń\":\"Ń\",\"Ň\":\"Ň\",\"Ņ\":\"Ņ\",\"Н\":\"Н\",\"​\":\"​\",\"\\n\":\" \",\"𝔑\":\"𝔑\",\"⁠\":\"⁠\",\" \":\" \",\"ℕ\":\"ℕ\",\"⫬\":\"⫬\",\"≢\":\"≢\",\"≭\":\"≭\",\"∦\":\"∦\",\"∉\":\"∉\",\"≠\":\"≠\",\"≂̸\":\"≂̸\",\"∄\":\"∄\",\"≯\":\"≯\",\"≱\":\"≱\",\"≧̸\":\"≧̸\",\"≫̸\":\"≫̸\",\"≹\":\"≹\",\"⩾̸\":\"⩾̸\",\"≵\":\"≵\",\"≎̸\":\"≎̸\",\"≏̸\":\"≏̸\",\"⋪\":\"⋪\",\"⧏̸\":\"⧏̸\",\"⋬\":\"⋬\",\"≮\":\"≮\",\"≰\":\"≰\",\"≸\":\"≸\",\"≪̸\":\"≪̸\",\"⩽̸\":\"⩽̸\",\"≴\":\"≴\",\"⪢̸\":\"⪢̸\",\"⪡̸\":\"⪡̸\",\"⊀\":\"⊀\",\"⪯̸\":\"⪯̸\",\"⋠\":\"⋠\",\"∌\":\"∌\",\"⋫\":\"⋫\",\"⧐̸\":\"⧐̸\",\"⋭\":\"⋭\",\"⊏̸\":\"⊏̸\",\"⋢\":\"⋢\",\"⊐̸\":\"⊐̸\",\"⋣\":\"⋣\",\"⊂⃒\":\"⊂⃒\",\"⊈\":\"⊈\",\"⊁\":\"⊁\",\"⪰̸\":\"⪰̸\",\"⋡\":\"⋡\",\"≿̸\":\"≿̸\",\"⊃⃒\":\"⊃⃒\",\"⊉\":\"⊉\",\"≁\":\"≁\",\"≄\":\"≄\",\"≇\":\"≇\",\"≉\":\"≉\",\"∤\":\"∤\",\"𝒩\":\"𝒩\",\"Ñ\":\"Ñ\",\"Ν\":\"Ν\",\"Œ\":\"Œ\",\"Ó\":\"Ó\",\"Ô\":\"Ô\",\"О\":\"О\",\"Ő\":\"Ő\",\"𝔒\":\"𝔒\",\"Ò\":\"Ò\",\"Ō\":\"Ō\",\"Ω\":\"Ω\",\"Ο\":\"Ο\",\"𝕆\":\"𝕆\",\"“\":\"“\",\"‘\":\"‘\",\"⩔\":\"⩔\",\"𝒪\":\"𝒪\",\"Ø\":\"Ø\",\"Õ\":\"Õ\",\"⨷\":\"⨷\",\"Ö\":\"Ö\",\"‾\":\"‾\",\"⏞\":\"⏞\",\"⎴\":\"⎴\",\"⏜\":\"⏜\",\"∂\":\"∂\",\"П\":\"П\",\"𝔓\":\"𝔓\",\"Φ\":\"Φ\",\"Π\":\"Π\",\"±\":\"±\",\"ℙ\":\"ℙ\",\"⪻\":\"⪻\",\"≺\":\"≺\",\"⪯\":\"⪯\",\"≼\":\"≼\",\"≾\":\"≾\",\"″\":\"″\",\"∏\":\"∏\",\"∝\":\"∝\",\"𝒫\":\"𝒫\",\"Ψ\":\"Ψ\",'\"':\""\",\"𝔔\":\"𝔔\",\"ℚ\":\"ℚ\",\"𝒬\":\"𝒬\",\"⤐\":\"⤐\",\"®\":\"®\",\"Ŕ\":\"Ŕ\",\"⟫\":\"⟫\",\"↠\":\"↠\",\"⤖\":\"⤖\",\"Ř\":\"Ř\",\"Ŗ\":\"Ŗ\",\"Р\":\"Р\",\"ℜ\":\"ℜ\",\"∋\":\"∋\",\"⇋\":\"⇋\",\"⥯\":\"⥯\",\"Ρ\":\"Ρ\",\"⟩\":\"⟩\",\"→\":\"→\",\"⇥\":\"⇥\",\"⇄\":\"⇄\",\"⌉\":\"⌉\",\"⟧\":\"⟧\",\"⥝\":\"⥝\",\"⇂\":\"⇂\",\"⥕\":\"⥕\",\"⌋\":\"⌋\",\"⊢\":\"⊢\",\"↦\":\"↦\",\"⥛\":\"⥛\",\"⊳\":\"⊳\",\"⧐\":\"⧐\",\"⊵\":\"⊵\",\"⥏\":\"⥏\",\"⥜\":\"⥜\",\"↾\":\"↾\",\"⥔\":\"⥔\",\"⇀\":\"⇀\",\"⥓\":\"⥓\",\"ℝ\":\"ℝ\",\"⥰\":\"⥰\",\"⇛\":\"⇛\",\"ℛ\":\"ℛ\",\"↱\":\"↱\",\"⧴\":\"⧴\",\"Щ\":\"Щ\",\"Ш\":\"Ш\",\"Ь\":\"Ь\",\"Ś\":\"Ś\",\"⪼\":\"⪼\",\"Š\":\"Š\",\"Ş\":\"Ş\",\"Ŝ\":\"Ŝ\",\"С\":\"С\",\"𝔖\":\"𝔖\",\"↑\":\"↑\",\"Σ\":\"Σ\",\"∘\":\"∘\",\"𝕊\":\"𝕊\",\"√\":\"√\",\"□\":\"□\",\"⊓\":\"⊓\",\"⊏\":\"⊏\",\"⊑\":\"⊑\",\"⊐\":\"⊐\",\"⊒\":\"⊒\",\"⊔\":\"⊔\",\"𝒮\":\"𝒮\",\"⋆\":\"⋆\",\"⋐\":\"⋐\",\"⊆\":\"⊆\",\"≻\":\"≻\",\"⪰\":\"⪰\",\"≽\":\"≽\",\"≿\":\"≿\",\"∑\":\"∑\",\"⋑\":\"⋑\",\"⊃\":\"⊃\",\"⊇\":\"⊇\",\"Þ\":\"Þ\",\"™\":\"™\",\"Ћ\":\"Ћ\",\"Ц\":\"Ц\",\"\\t\":\" \",\"Τ\":\"Τ\",\"Ť\":\"Ť\",\"Ţ\":\"Ţ\",\"Т\":\"Т\",\"𝔗\":\"𝔗\",\"∴\":\"∴\",\"Θ\":\"Θ\",\"  \":\"  \",\" \":\" \",\"∼\":\"∼\",\"≃\":\"≃\",\"≅\":\"≅\",\"≈\":\"≈\",\"𝕋\":\"𝕋\",\"⃛\":\"⃛\",\"𝒯\":\"𝒯\",\"Ŧ\":\"Ŧ\",\"Ú\":\"Ú\",\"↟\":\"↟\",\"⥉\":\"⥉\",\"Ў\":\"Ў\",\"Ŭ\":\"Ŭ\",\"Û\":\"Û\",\"У\":\"У\",\"Ű\":\"Ű\",\"𝔘\":\"𝔘\",\"Ù\":\"Ù\",\"Ū\":\"Ū\",_:\"_\",\"⏟\":\"⏟\",\"⎵\":\"⎵\",\"⏝\":\"⏝\",\"⋃\":\"⋃\",\"⊎\":\"⊎\",\"Ų\":\"Ų\",\"𝕌\":\"𝕌\",\"⤒\":\"⤒\",\"⇅\":\"⇅\",\"↕\":\"↕\",\"⥮\":\"⥮\",\"⊥\":\"⊥\",\"↥\":\"↥\",\"↖\":\"↖\",\"↗\":\"↗\",\"ϒ\":\"ϒ\",\"Υ\":\"Υ\",\"Ů\":\"Ů\",\"𝒰\":\"𝒰\",\"Ũ\":\"Ũ\",\"Ü\":\"Ü\",\"⊫\":\"⊫\",\"⫫\":\"⫫\",\"В\":\"В\",\"⊩\":\"⊩\",\"⫦\":\"⫦\",\"⋁\":\"⋁\",\"‖\":\"‖\",\"∣\":\"∣\",\"|\":\"|\",\"❘\":\"❘\",\"≀\":\"≀\",\" \":\" \",\"𝔙\":\"𝔙\",\"𝕍\":\"𝕍\",\"𝒱\":\"𝒱\",\"⊪\":\"⊪\",\"Ŵ\":\"Ŵ\",\"⋀\":\"⋀\",\"𝔚\":\"𝔚\",\"𝕎\":\"𝕎\",\"𝒲\":\"𝒲\",\"𝔛\":\"𝔛\",\"Ξ\":\"Ξ\",\"𝕏\":\"𝕏\",\"𝒳\":\"𝒳\",\"Я\":\"Я\",\"Ї\":\"Ї\",\"Ю\":\"Ю\",\"Ý\":\"Ý\",\"Ŷ\":\"Ŷ\",\"Ы\":\"Ы\",\"𝔜\":\"𝔜\",\"𝕐\":\"𝕐\",\"𝒴\":\"𝒴\",\"Ÿ\":\"Ÿ\",\"Ж\":\"Ж\",\"Ź\":\"Ź\",\"Ž\":\"Ž\",\"З\":\"З\",\"Ż\":\"Ż\",\"Ζ\":\"Ζ\",\"ℨ\":\"ℨ\",\"ℤ\":\"ℤ\",\"𝒵\":\"𝒵\",\"á\":\"á\",\"ă\":\"ă\",\"∾\":\"∾\",\"∾̳\":\"∾̳\",\"∿\":\"∿\",\"â\":\"â\",\"а\":\"а\",\"æ\":\"æ\",\"𝔞\":\"𝔞\",\"à\":\"à\",\"ℵ\":\"ℵ\",\"α\":\"α\",\"ā\":\"ā\",\"⨿\":\"⨿\",\"∧\":\"∧\",\"⩕\":\"⩕\",\"⩜\":\"⩜\",\"⩘\":\"⩘\",\"⩚\":\"⩚\",\"∠\":\"∠\",\"⦤\":\"⦤\",\"∡\":\"∡\",\"⦨\":\"⦨\",\"⦩\":\"⦩\",\"⦪\":\"⦪\",\"⦫\":\"⦫\",\"⦬\":\"⦬\",\"⦭\":\"⦭\",\"⦮\":\"⦮\",\"⦯\":\"⦯\",\"∟\":\"∟\",\"⊾\":\"⊾\",\"⦝\":\"⦝\",\"∢\":\"∢\",\"⍼\":\"⍼\",\"ą\":\"ą\",\"𝕒\":\"𝕒\",\"⩰\":\"⩰\",\"⩯\":\"⩯\",\"≊\":\"≊\",\"≋\":\"≋\",\"'\":\"'\",\"å\":\"å\",\"𝒶\":\"𝒶\",\"*\":\"*\",\"ã\":\"ã\",\"ä\":\"ä\",\"⨑\":\"⨑\",\"⫭\":\"⫭\",\"≌\":\"≌\",\"϶\":\"϶\",\"‵\":\"‵\",\"∽\":\"∽\",\"⋍\":\"⋍\",\"⊽\":\"⊽\",\"⌅\":\"⌅\",\"⎶\":\"⎶\",\"б\":\"б\",\"„\":\"„\",\"⦰\":\"⦰\",\"β\":\"β\",\"ℶ\":\"ℶ\",\"≬\":\"≬\",\"𝔟\":\"𝔟\",\"◯\":\"◯\",\"⨀\":\"⨀\",\"⨁\":\"⨁\",\"⨂\":\"⨂\",\"⨆\":\"⨆\",\"★\":\"★\",\"▽\":\"▽\",\"△\":\"△\",\"⨄\":\"⨄\",\"⤍\":\"⤍\",\"⧫\":\"⧫\",\"▴\":\"▴\",\"▾\":\"▾\",\"◂\":\"◂\",\"▸\":\"▸\",\"␣\":\"␣\",\"▒\":\"▒\",\"░\":\"░\",\"▓\":\"▓\",\"█\":\"█\",\"=⃥\":\"=⃥\",\"≡⃥\":\"≡⃥\",\"⌐\":\"⌐\",\"𝕓\":\"𝕓\",\"⋈\":\"⋈\",\"╗\":\"╗\",\"╔\":\"╔\",\"╖\":\"╖\",\"╓\":\"╓\",\"═\":\"═\",\"╦\":\"╦\",\"╩\":\"╩\",\"╤\":\"╤\",\"╧\":\"╧\",\"╝\":\"╝\",\"╚\":\"╚\",\"╜\":\"╜\",\"╙\":\"╙\",\"║\":\"║\",\"╬\":\"╬\",\"╣\":\"╣\",\"╠\":\"╠\",\"╫\":\"╫\",\"╢\":\"╢\",\"╟\":\"╟\",\"⧉\":\"⧉\",\"╕\":\"╕\",\"╒\":\"╒\",\"┐\":\"┐\",\"┌\":\"┌\",\"╥\":\"╥\",\"╨\":\"╨\",\"┬\":\"┬\",\"┴\":\"┴\",\"⊟\":\"⊟\",\"⊞\":\"⊞\",\"⊠\":\"⊠\",\"╛\":\"╛\",\"╘\":\"╘\",\"┘\":\"┘\",\"└\":\"└\",\"│\":\"│\",\"╪\":\"╪\",\"╡\":\"╡\",\"╞\":\"╞\",\"┼\":\"┼\",\"┤\":\"┤\",\"├\":\"├\",\"¦\":\"¦\",\"𝒷\":\"𝒷\",\"⁏\":\"⁏\",\"\\\\\":\"\\",\"⧅\":\"⧅\",\"⟈\":\"⟈\",\"•\":\"•\",\"⪮\":\"⪮\",\"ć\":\"ć\",\"∩\":\"∩\",\"⩄\":\"⩄\",\"⩉\":\"⩉\",\"⩋\":\"⩋\",\"⩇\":\"⩇\",\"⩀\":\"⩀\",\"∩︀\":\"∩︀\",\"⁁\":\"⁁\",\"⩍\":\"⩍\",\"č\":\"č\",\"ç\":\"ç\",\"ĉ\":\"ĉ\",\"⩌\":\"⩌\",\"⩐\":\"⩐\",\"ċ\":\"ċ\",\"⦲\":\"⦲\",\"¢\":\"¢\",\"𝔠\":\"𝔠\",\"ч\":\"ч\",\"✓\":\"✓\",\"χ\":\"χ\",\"○\":\"○\",\"⧃\":\"⧃\",\"ˆ\":\"ˆ\",\"≗\":\"≗\",\"↺\":\"↺\",\"↻\":\"↻\",\"Ⓢ\":\"Ⓢ\",\"⊛\":\"⊛\",\"⊚\":\"⊚\",\"⊝\":\"⊝\",\"⨐\":\"⨐\",\"⫯\":\"⫯\",\"⧂\":\"⧂\",\"♣\":\"♣\",\":\":\":\",\",\":\",\",\"@\":\"@\",\"∁\":\"∁\",\"⩭\":\"⩭\",\"𝕔\":\"𝕔\",\"℗\":\"℗\",\"↵\":\"↵\",\"✗\":\"✗\",\"𝒸\":\"𝒸\",\"⫏\":\"⫏\",\"⫑\":\"⫑\",\"⫐\":\"⫐\",\"⫒\":\"⫒\",\"⋯\":\"⋯\",\"⤸\":\"⤸\",\"⤵\":\"⤵\",\"⋞\":\"⋞\",\"⋟\":\"⋟\",\"↶\":\"↶\",\"⤽\":\"⤽\",\"∪\":\"∪\",\"⩈\":\"⩈\",\"⩆\":\"⩆\",\"⩊\":\"⩊\",\"⊍\":\"⊍\",\"⩅\":\"⩅\",\"∪︀\":\"∪︀\",\"↷\":\"↷\",\"⤼\":\"⤼\",\"⋎\":\"⋎\",\"⋏\":\"⋏\",\"¤\":\"¤\",\"∱\":\"∱\",\"⌭\":\"⌭\",\"⥥\":\"⥥\",\"†\":\"†\",\"ℸ\":\"ℸ\",\"‐\":\"‐\",\"⤏\":\"⤏\",\"ď\":\"ď\",\"д\":\"д\",\"⇊\":\"⇊\",\"⩷\":\"⩷\",\"°\":\"°\",\"δ\":\"δ\",\"⦱\":\"⦱\",\"⥿\":\"⥿\",\"𝔡\":\"𝔡\",\"♦\":\"♦\",\"ϝ\":\"ϝ\",\"⋲\":\"⋲\",\"÷\":\"÷\",\"⋇\":\"⋇\",\"ђ\":\"ђ\",\"⌞\":\"⌞\",\"⌍\":\"⌍\",$:\"$\",\"𝕕\":\"𝕕\",\"≑\":\"≑\",\"∸\":\"∸\",\"∔\":\"∔\",\"⊡\":\"⊡\",\"⌟\":\"⌟\",\"⌌\":\"⌌\",\"𝒹\":\"𝒹\",\"ѕ\":\"ѕ\",\"⧶\":\"⧶\",\"đ\":\"đ\",\"⋱\":\"⋱\",\"▿\":\"▿\",\"⦦\":\"⦦\",\"џ\":\"џ\",\"⟿\":\"⟿\",\"é\":\"é\",\"⩮\":\"⩮\",\"ě\":\"ě\",\"≖\":\"≖\",\"ê\":\"ê\",\"≕\":\"≕\",\"э\":\"э\",\"ė\":\"ė\",\"≒\":\"≒\",\"𝔢\":\"𝔢\",\"⪚\":\"⪚\",\"è\":\"è\",\"⪖\":\"⪖\",\"⪘\":\"⪘\",\"⪙\":\"⪙\",\"⏧\":\"⏧\",\"ℓ\":\"ℓ\",\"⪕\":\"⪕\",\"⪗\":\"⪗\",\"ē\":\"ē\",\"∅\":\"∅\",\" \":\" \",\" \":\" \",\" \":\" \",\"ŋ\":\"ŋ\",\" \":\" \",\"ę\":\"ę\",\"𝕖\":\"𝕖\",\"⋕\":\"⋕\",\"⧣\":\"⧣\",\"⩱\":\"⩱\",\"ε\":\"ε\",\"ϵ\":\"ϵ\",\"=\":\"=\",\"≟\":\"≟\",\"⩸\":\"⩸\",\"⧥\":\"⧥\",\"≓\":\"≓\",\"⥱\":\"⥱\",\"ℯ\":\"ℯ\",\"η\":\"η\",\"ð\":\"ð\",\"ë\":\"ë\",\"€\":\"€\",\"!\":\"!\",\"ф\":\"ф\",\"♀\":\"♀\",\"ffi\":\"ffi\",\"ff\":\"ff\",\"ffl\":\"ffl\",\"𝔣\":\"𝔣\",\"fi\":\"fi\",fj:\"fj\",\"♭\":\"♭\",\"fl\":\"fl\",\"▱\":\"▱\",\"ƒ\":\"ƒ\",\"𝕗\":\"𝕗\",\"⋔\":\"⋔\",\"⫙\":\"⫙\",\"⨍\":\"⨍\",\"½\":\"½\",\"⅓\":\"⅓\",\"¼\":\"¼\",\"⅕\":\"⅕\",\"⅙\":\"⅙\",\"⅛\":\"⅛\",\"⅔\":\"⅔\",\"⅖\":\"⅖\",\"¾\":\"¾\",\"⅗\":\"⅗\",\"⅜\":\"⅜\",\"⅘\":\"⅘\",\"⅚\":\"⅚\",\"⅝\":\"⅝\",\"⅞\":\"⅞\",\"⁄\":\"⁄\",\"⌢\":\"⌢\",\"𝒻\":\"𝒻\",\"⪌\":\"⪌\",\"ǵ\":\"ǵ\",\"γ\":\"γ\",\"⪆\":\"⪆\",\"ğ\":\"ğ\",\"ĝ\":\"ĝ\",\"г\":\"г\",\"ġ\":\"ġ\",\"⪩\":\"⪩\",\"⪀\":\"⪀\",\"⪂\":\"⪂\",\"⪄\":\"⪄\",\"⋛︀\":\"⋛︀\",\"⪔\":\"⪔\",\"𝔤\":\"𝔤\",\"ℷ\":\"ℷ\",\"ѓ\":\"ѓ\",\"⪒\":\"⪒\",\"⪥\":\"⪥\",\"⪤\":\"⪤\",\"≩\":\"≩\",\"⪊\":\"⪊\",\"⪈\":\"⪈\",\"⋧\":\"⋧\",\"𝕘\":\"𝕘\",\"ℊ\":\"ℊ\",\"⪎\":\"⪎\",\"⪐\":\"⪐\",\"⪧\":\"⪧\",\"⩺\":\"⩺\",\"⋗\":\"⋗\",\"⦕\":\"⦕\",\"⩼\":\"⩼\",\"⥸\":\"⥸\",\"≩︀\":\"≩︀\",\"ъ\":\"ъ\",\"⥈\":\"⥈\",\"↭\":\"↭\",\"ℏ\":\"ℏ\",\"ĥ\":\"ĥ\",\"♥\":\"♥\",\"…\":\"…\",\"⊹\":\"⊹\",\"𝔥\":\"𝔥\",\"⤥\":\"⤥\",\"⤦\":\"⤦\",\"⇿\":\"⇿\",\"∻\":\"∻\",\"↩\":\"↩\",\"↪\":\"↪\",\"𝕙\":\"𝕙\",\"―\":\"―\",\"𝒽\":\"𝒽\",\"ħ\":\"ħ\",\"⁃\":\"⁃\",\"í\":\"í\",\"î\":\"î\",\"и\":\"и\",\"е\":\"е\",\"¡\":\"¡\",\"𝔦\":\"𝔦\",\"ì\":\"ì\",\"⨌\":\"⨌\",\"∭\":\"∭\",\"⧜\":\"⧜\",\"℩\":\"℩\",\"ij\":\"ij\",\"ī\":\"ī\",\"ı\":\"ı\",\"⊷\":\"⊷\",\"Ƶ\":\"Ƶ\",\"℅\":\"℅\",\"∞\":\"∞\",\"⧝\":\"⧝\",\"⊺\":\"⊺\",\"⨗\":\"⨗\",\"⨼\":\"⨼\",\"ё\":\"ё\",\"į\":\"į\",\"𝕚\":\"𝕚\",\"ι\":\"ι\",\"¿\":\"¿\",\"𝒾\":\"𝒾\",\"⋹\":\"⋹\",\"⋵\":\"⋵\",\"⋴\":\"⋴\",\"⋳\":\"⋳\",\"ĩ\":\"ĩ\",\"і\":\"і\",\"ï\":\"ï\",\"ĵ\":\"ĵ\",\"й\":\"й\",\"𝔧\":\"𝔧\",\"ȷ\":\"ȷ\",\"𝕛\":\"𝕛\",\"𝒿\":\"𝒿\",\"ј\":\"ј\",\"є\":\"є\",\"κ\":\"κ\",\"ϰ\":\"ϰ\",\"ķ\":\"ķ\",\"к\":\"к\",\"𝔨\":\"𝔨\",\"ĸ\":\"ĸ\",\"х\":\"х\",\"ќ\":\"ќ\",\"𝕜\":\"𝕜\",\"𝓀\":\"𝓀\",\"⤛\":\"⤛\",\"⤎\":\"⤎\",\"⪋\":\"⪋\",\"⥢\":\"⥢\",\"ĺ\":\"ĺ\",\"⦴\":\"⦴\",\"λ\":\"λ\",\"⦑\":\"⦑\",\"⪅\":\"⪅\",\"«\":\"«\",\"⤟\":\"⤟\",\"⤝\":\"⤝\",\"↫\":\"↫\",\"⤹\":\"⤹\",\"⥳\":\"⥳\",\"↢\":\"↢\",\"⪫\":\"⪫\",\"⤙\":\"⤙\",\"⪭\":\"⪭\",\"⪭︀\":\"⪭︀\",\"⤌\":\"⤌\",\"❲\":\"❲\",\"{\":\"{\",\"[\":\"[\",\"⦋\":\"⦋\",\"⦏\":\"⦏\",\"⦍\":\"⦍\",\"ľ\":\"ľ\",\"ļ\":\"ļ\",\"л\":\"л\",\"⤶\":\"⤶\",\"⥧\":\"⥧\",\"⥋\":\"⥋\",\"↲\":\"↲\",\"≤\":\"≤\",\"⇇\":\"⇇\",\"⋋\":\"⋋\",\"⪨\":\"⪨\",\"⩿\":\"⩿\",\"⪁\":\"⪁\",\"⪃\":\"⪃\",\"⋚︀\":\"⋚︀\",\"⪓\":\"⪓\",\"⋖\":\"⋖\",\"⥼\":\"⥼\",\"𝔩\":\"𝔩\",\"⪑\":\"⪑\",\"⥪\":\"⥪\",\"▄\":\"▄\",\"љ\":\"љ\",\"⥫\":\"⥫\",\"◺\":\"◺\",\"ŀ\":\"ŀ\",\"⎰\":\"⎰\",\"≨\":\"≨\",\"⪉\":\"⪉\",\"⪇\":\"⪇\",\"⋦\":\"⋦\",\"⟬\":\"⟬\",\"⇽\":\"⇽\",\"⟼\":\"⟼\",\"↬\":\"↬\",\"⦅\":\"⦅\",\"𝕝\":\"𝕝\",\"⨭\":\"⨭\",\"⨴\":\"⨴\",\"∗\":\"∗\",\"◊\":\"◊\",\"(\":\"(\",\"⦓\":\"⦓\",\"⥭\":\"⥭\",\"‎\":\"‎\",\"⊿\":\"⊿\",\"‹\":\"‹\",\"𝓁\":\"𝓁\",\"⪍\":\"⪍\",\"⪏\":\"⪏\",\"‚\":\"‚\",\"ł\":\"ł\",\"⪦\":\"⪦\",\"⩹\":\"⩹\",\"⋉\":\"⋉\",\"⥶\":\"⥶\",\"⩻\":\"⩻\",\"⦖\":\"⦖\",\"◃\":\"◃\",\"⥊\":\"⥊\",\"⥦\":\"⥦\",\"≨︀\":\"≨︀\",\"∺\":\"∺\",\"¯\":\"¯\",\"♂\":\"♂\",\"✠\":\"✠\",\"▮\":\"▮\",\"⨩\":\"⨩\",\"м\":\"м\",\"—\":\"—\",\"𝔪\":\"𝔪\",\"℧\":\"℧\",\"µ\":\"µ\",\"⫰\":\"⫰\",\"−\":\"−\",\"⨪\":\"⨪\",\"⫛\":\"⫛\",\"⊧\":\"⊧\",\"𝕞\":\"𝕞\",\"𝓂\":\"𝓂\",\"μ\":\"μ\",\"⊸\":\"⊸\",\"⋙̸\":\"⋙̸\",\"≫⃒\":\"≫⃒\",\"⇍\":\"⇍\",\"⇎\":\"⇎\",\"⋘̸\":\"⋘̸\",\"≪⃒\":\"≪⃒\",\"⇏\":\"⇏\",\"⊯\":\"⊯\",\"⊮\":\"⊮\",\"ń\":\"ń\",\"∠⃒\":\"∠⃒\",\"⩰̸\":\"⩰̸\",\"≋̸\":\"≋̸\",\"ʼn\":\"ʼn\",\"♮\":\"♮\",\"⩃\":\"⩃\",\"ň\":\"ň\",\"ņ\":\"ņ\",\"⩭̸\":\"⩭̸\",\"⩂\":\"⩂\",\"н\":\"н\",\"–\":\"–\",\"⇗\":\"⇗\",\"⤤\":\"⤤\",\"≐̸\":\"≐̸\",\"⤨\":\"⤨\",\"𝔫\":\"𝔫\",\"↮\":\"↮\",\"⫲\":\"⫲\",\"⋼\":\"⋼\",\"⋺\":\"⋺\",\"њ\":\"њ\",\"≦̸\":\"≦̸\",\"↚\":\"↚\",\"‥\":\"‥\",\"𝕟\":\"𝕟\",\"¬\":\"¬\",\"⋹̸\":\"⋹̸\",\"⋵̸\":\"⋵̸\",\"⋷\":\"⋷\",\"⋶\":\"⋶\",\"⋾\":\"⋾\",\"⋽\":\"⋽\",\"⫽⃥\":\"⫽⃥\",\"∂̸\":\"∂̸\",\"⨔\":\"⨔\",\"↛\":\"↛\",\"⤳̸\":\"⤳̸\",\"↝̸\":\"↝̸\",\"𝓃\":\"𝓃\",\"⊄\":\"⊄\",\"⫅̸\":\"⫅̸\",\"⊅\":\"⊅\",\"⫆̸\":\"⫆̸\",\"ñ\":\"ñ\",\"ν\":\"ν\",\"#\":\"#\",\"№\":\"№\",\" \":\" \",\"⊭\":\"⊭\",\"⤄\":\"⤄\",\"≍⃒\":\"≍⃒\",\"⊬\":\"⊬\",\"≥⃒\":\"≥⃒\",\">⃒\":\">⃒\",\"⧞\":\"⧞\",\"⤂\":\"⤂\",\"≤⃒\":\"≤⃒\",\"<⃒\":\"<⃒\",\"⊴⃒\":\"⊴⃒\",\"⤃\":\"⤃\",\"⊵⃒\":\"⊵⃒\",\"∼⃒\":\"∼⃒\",\"⇖\":\"⇖\",\"⤣\":\"⤣\",\"⤧\":\"⤧\",\"ó\":\"ó\",\"ô\":\"ô\",\"о\":\"о\",\"ő\":\"ő\",\"⨸\":\"⨸\",\"⦼\":\"⦼\",\"œ\":\"œ\",\"⦿\":\"⦿\",\"𝔬\":\"𝔬\",\"˛\":\"˛\",\"ò\":\"ò\",\"⧁\":\"⧁\",\"⦵\":\"⦵\",\"⦾\":\"⦾\",\"⦻\":\"⦻\",\"⧀\":\"⧀\",\"ō\":\"ō\",\"ω\":\"ω\",\"ο\":\"ο\",\"⦶\":\"⦶\",\"𝕠\":\"𝕠\",\"⦷\":\"⦷\",\"⦹\":\"⦹\",\"∨\":\"∨\",\"⩝\":\"⩝\",\"ℴ\":\"ℴ\",\"ª\":\"ª\",\"º\":\"º\",\"⊶\":\"⊶\",\"⩖\":\"⩖\",\"⩗\":\"⩗\",\"⩛\":\"⩛\",\"ø\":\"ø\",\"⊘\":\"⊘\",\"õ\":\"õ\",\"⨶\":\"⨶\",\"ö\":\"ö\",\"⌽\":\"⌽\",\"¶\":\"¶\",\"⫳\":\"⫳\",\"⫽\":\"⫽\",\"п\":\"п\",\"%\":\"%\",\".\":\".\",\"‰\":\"‰\",\"‱\":\"‱\",\"𝔭\":\"𝔭\",\"φ\":\"φ\",\"ϕ\":\"ϕ\",\"☎\":\"☎\",\"π\":\"π\",\"ϖ\":\"ϖ\",\"ℎ\":\"ℎ\",\"+\":\"+\",\"⨣\":\"⨣\",\"⨢\":\"⨢\",\"⨥\":\"⨥\",\"⩲\":\"⩲\",\"⨦\":\"⨦\",\"⨧\":\"⨧\",\"⨕\":\"⨕\",\"𝕡\":\"𝕡\",\"£\":\"£\",\"⪳\":\"⪳\",\"⪷\":\"⪷\",\"⪹\":\"⪹\",\"⪵\":\"⪵\",\"⋨\":\"⋨\",\"′\":\"′\",\"⌮\":\"⌮\",\"⌒\":\"⌒\",\"⌓\":\"⌓\",\"⊰\":\"⊰\",\"𝓅\":\"𝓅\",\"ψ\":\"ψ\",\" \":\" \",\"𝔮\":\"𝔮\",\"𝕢\":\"𝕢\",\"⁗\":\"⁗\",\"𝓆\":\"𝓆\",\"⨖\":\"⨖\",\"?\":\"?\",\"⤜\":\"⤜\",\"⥤\":\"⥤\",\"∽̱\":\"∽̱\",\"ŕ\":\"ŕ\",\"⦳\":\"⦳\",\"⦒\":\"⦒\",\"⦥\":\"⦥\",\"»\":\"»\",\"⥵\":\"⥵\",\"⤠\":\"⤠\",\"⤳\":\"⤳\",\"⤞\":\"⤞\",\"⥅\":\"⥅\",\"⥴\":\"⥴\",\"↣\":\"↣\",\"↝\":\"↝\",\"⤚\":\"⤚\",\"∶\":\"∶\",\"❳\":\"❳\",\"}\":\"}\",\"]\":\"]\",\"⦌\":\"⦌\",\"⦎\":\"⦎\",\"⦐\":\"⦐\",\"ř\":\"ř\",\"ŗ\":\"ŗ\",\"р\":\"р\",\"⤷\":\"⤷\",\"⥩\":\"⥩\",\"↳\":\"↳\",\"▭\":\"▭\",\"⥽\":\"⥽\",\"𝔯\":\"𝔯\",\"⥬\":\"⥬\",\"ρ\":\"ρ\",\"ϱ\":\"ϱ\",\"⇉\":\"⇉\",\"⋌\":\"⋌\",\"˚\":\"˚\",\"‏\":\"‏\",\"⎱\":\"⎱\",\"⫮\":\"⫮\",\"⟭\":\"⟭\",\"⇾\":\"⇾\",\"⦆\":\"⦆\",\"𝕣\":\"𝕣\",\"⨮\":\"⨮\",\"⨵\":\"⨵\",\")\":\")\",\"⦔\":\"⦔\",\"⨒\":\"⨒\",\"›\":\"›\",\"𝓇\":\"𝓇\",\"⋊\":\"⋊\",\"▹\":\"▹\",\"⧎\":\"⧎\",\"⥨\":\"⥨\",\"℞\":\"℞\",\"ś\":\"ś\",\"⪴\":\"⪴\",\"⪸\":\"⪸\",\"š\":\"š\",\"ş\":\"ş\",\"ŝ\":\"ŝ\",\"⪶\":\"⪶\",\"⪺\":\"⪺\",\"⋩\":\"⋩\",\"⨓\":\"⨓\",\"с\":\"с\",\"⋅\":\"⋅\",\"⩦\":\"⩦\",\"⇘\":\"⇘\",\"§\":\"§\",\";\":\";\",\"⤩\":\"⤩\",\"✶\":\"✶\",\"𝔰\":\"𝔰\",\"♯\":\"♯\",\"щ\":\"щ\",\"ш\":\"ш\",\"­\":\"­\",\"σ\":\"σ\",\"ς\":\"ς\",\"⩪\":\"⩪\",\"⪞\":\"⪞\",\"⪠\":\"⪠\",\"⪝\":\"⪝\",\"⪟\":\"⪟\",\"≆\":\"≆\",\"⨤\":\"⨤\",\"⥲\":\"⥲\",\"⨳\":\"⨳\",\"⧤\":\"⧤\",\"⌣\":\"⌣\",\"⪪\":\"⪪\",\"⪬\":\"⪬\",\"⪬︀\":\"⪬︀\",\"ь\":\"ь\",\"/\":\"/\",\"⧄\":\"⧄\",\"⌿\":\"⌿\",\"𝕤\":\"𝕤\",\"♠\":\"♠\",\"⊓︀\":\"⊓︀\",\"⊔︀\":\"⊔︀\",\"𝓈\":\"𝓈\",\"☆\":\"☆\",\"⊂\":\"⊂\",\"⫅\":\"⫅\",\"⪽\":\"⪽\",\"⫃\":\"⫃\",\"⫁\":\"⫁\",\"⫋\":\"⫋\",\"⊊\":\"⊊\",\"⪿\":\"⪿\",\"⥹\":\"⥹\",\"⫇\":\"⫇\",\"⫕\":\"⫕\",\"⫓\":\"⫓\",\"♪\":\"♪\",\"¹\":\"¹\",\"²\":\"²\",\"³\":\"³\",\"⫆\":\"⫆\",\"⪾\":\"⪾\",\"⫘\":\"⫘\",\"⫄\":\"⫄\",\"⟉\":\"⟉\",\"⫗\":\"⫗\",\"⥻\":\"⥻\",\"⫂\":\"⫂\",\"⫌\":\"⫌\",\"⊋\":\"⊋\",\"⫀\":\"⫀\",\"⫈\":\"⫈\",\"⫔\":\"⫔\",\"⫖\":\"⫖\",\"⇙\":\"⇙\",\"⤪\":\"⤪\",\"ß\":\"ß\",\"⌖\":\"⌖\",\"τ\":\"τ\",\"ť\":\"ť\",\"ţ\":\"ţ\",\"т\":\"т\",\"⌕\":\"⌕\",\"𝔱\":\"𝔱\",\"θ\":\"θ\",\"ϑ\":\"ϑ\",\"þ\":\"þ\",\"×\":\"×\",\"⨱\":\"⨱\",\"⨰\":\"⨰\",\"⌶\":\"⌶\",\"⫱\":\"⫱\",\"𝕥\":\"𝕥\",\"⫚\":\"⫚\",\"‴\":\"‴\",\"▵\":\"▵\",\"≜\":\"≜\",\"◬\":\"◬\",\"⨺\":\"⨺\",\"⨹\":\"⨹\",\"⧍\":\"⧍\",\"⨻\":\"⨻\",\"⏢\":\"⏢\",\"𝓉\":\"𝓉\",\"ц\":\"ц\",\"ћ\":\"ћ\",\"ŧ\":\"ŧ\",\"⥣\":\"⥣\",\"ú\":\"ú\",\"ў\":\"ў\",\"ŭ\":\"ŭ\",\"û\":\"û\",\"у\":\"у\",\"ű\":\"ű\",\"⥾\":\"⥾\",\"𝔲\":\"𝔲\",\"ù\":\"ù\",\"▀\":\"▀\",\"⌜\":\"⌜\",\"⌏\":\"⌏\",\"◸\":\"◸\",\"ū\":\"ū\",\"ų\":\"ų\",\"𝕦\":\"𝕦\",\"υ\":\"υ\",\"⇈\":\"⇈\",\"⌝\":\"⌝\",\"⌎\":\"⌎\",\"ů\":\"ů\",\"◹\":\"◹\",\"𝓊\":\"𝓊\",\"⋰\":\"⋰\",\"ũ\":\"ũ\",\"ü\":\"ü\",\"⦧\":\"⦧\",\"⫨\":\"⫨\",\"⫩\":\"⫩\",\"⦜\":\"⦜\",\"⊊︀\":\"⊊︀\",\"⫋︀\":\"⫋︀\",\"⊋︀\":\"⊋︀\",\"⫌︀\":\"⫌︀\",\"в\":\"в\",\"⊻\":\"⊻\",\"≚\":\"≚\",\"⋮\":\"⋮\",\"𝔳\":\"𝔳\",\"𝕧\":\"𝕧\",\"𝓋\":\"𝓋\",\"⦚\":\"⦚\",\"ŵ\":\"ŵ\",\"⩟\":\"⩟\",\"≙\":\"≙\",\"℘\":\"℘\",\"𝔴\":\"𝔴\",\"𝕨\":\"𝕨\",\"𝓌\":\"𝓌\",\"𝔵\":\"𝔵\",\"ξ\":\"ξ\",\"⋻\":\"⋻\",\"𝕩\":\"𝕩\",\"𝓍\":\"𝓍\",\"ý\":\"ý\",\"я\":\"я\",\"ŷ\":\"ŷ\",\"ы\":\"ы\",\"¥\":\"¥\",\"𝔶\":\"𝔶\",\"ї\":\"ї\",\"𝕪\":\"𝕪\",\"𝓎\":\"𝓎\",\"ю\":\"ю\",\"ÿ\":\"ÿ\",\"ź\":\"ź\",\"ž\":\"ž\",\"з\":\"з\",\"ż\":\"ż\",\"ζ\":\"ζ\",\"𝔷\":\"𝔷\",\"ж\":\"ж\",\"⇝\":\"⇝\",\"𝕫\":\"𝕫\",\"𝓏\":\"𝓏\",\"‍\":\"‍\",\"‌\":\"‌\"}}};\n//# sourceMappingURL=./named-references.js.map\n\n//# sourceURL=webpack://tududi/./node_modules/html-entities/lib/named-references.js?"); - -/***/ }), - -/***/ "./node_modules/html-entities/lib/numeric-unicode-map.js": -/*!***************************************************************!*\ - !*** ./node_modules/html-entities/lib/numeric-unicode-map.js ***! - \***************************************************************/ -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; -eval("Object.defineProperty(exports, \"__esModule\", ({value:true}));exports.numericUnicodeMap={0:65533,128:8364,130:8218,131:402,132:8222,133:8230,134:8224,135:8225,136:710,137:8240,138:352,139:8249,140:338,142:381,145:8216,146:8217,147:8220,148:8221,149:8226,150:8211,151:8212,152:732,153:8482,154:353,155:8250,156:339,158:382,159:376};\n//# sourceMappingURL=./numeric-unicode-map.js.map\n\n//# sourceURL=webpack://tududi/./node_modules/html-entities/lib/numeric-unicode-map.js?"); - -/***/ }), - -/***/ "./node_modules/html-entities/lib/surrogate-pairs.js": -/*!***********************************************************!*\ - !*** ./node_modules/html-entities/lib/surrogate-pairs.js ***! - \***********************************************************/ -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; -eval("Object.defineProperty(exports, \"__esModule\", ({value:true}));exports.fromCodePoint=String.fromCodePoint||function(astralCodePoint){return String.fromCharCode(Math.floor((astralCodePoint-65536)/1024)+55296,(astralCodePoint-65536)%1024+56320)};exports.getCodePoint=String.prototype.codePointAt?function(input,position){return input.codePointAt(position)}:function(input,position){return(input.charCodeAt(position)-55296)*1024+input.charCodeAt(position+1)-56320+65536};exports.highSurrogateFrom=55296;exports.highSurrogateTo=56319;\n//# sourceMappingURL=./surrogate-pairs.js.map\n\n//# sourceURL=webpack://tududi/./node_modules/html-entities/lib/surrogate-pairs.js?"); - -/***/ }), - -/***/ "./node_modules/html-parse-stringify/dist/html-parse-stringify.module.js": -/*!*******************************************************************************!*\ - !*** ./node_modules/html-parse-stringify/dist/html-parse-stringify.module.js ***! - \*******************************************************************************/ -/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var void_elements__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! void-elements */ \"./node_modules/void-elements/index.js\");\n/* harmony import */ var void_elements__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(void_elements__WEBPACK_IMPORTED_MODULE_0__);\nvar t=/\\s([^'\"/\\s><]+?)[\\s/>]|([^\\s=]+)=\\s?(\".*?\"|'.*?')/g;function n(n){var r={type:\"tag\",name:\"\",voidElement:!1,attrs:{},children:[]},i=n.match(/<\\/?([^\\s]+?)[/\\s>]/);if(i&&(r.name=i[1],((void_elements__WEBPACK_IMPORTED_MODULE_0___default())[i[1]]||\"/\"===n.charAt(n.length-2))&&(r.voidElement=!0),r.name.startsWith(\"!--\"))){var s=n.indexOf(\"--\\x3e\");return{type:\"comment\",comment:-1!==s?n.slice(4,s):\"\"}}for(var a=new RegExp(t),c=null;null!==(c=a.exec(n));)if(c[0].trim())if(c[1]){var o=c[1].trim(),l=[o,\"\"];o.indexOf(\"=\")>-1&&(l=o.split(\"=\")),r.attrs[l[0]]=l[1],a.lastIndex--}else c[2]&&(r.attrs[c[2]]=c[3].trim().substring(1,c[3].length-1));return r}var r=/<[a-zA-Z0-9\\-\\!\\/](?:\"[^\"]*\"|'[^']*'|[^'\">])*>/g,i=/^\\s*$/,s=Object.create(null);function a(e,t){switch(t.type){case\"text\":return e+t.content;case\"tag\":return e+=\"<\"+t.name+(t.attrs?function(e){var t=[];for(var n in e)t.push(n+'=\"'+e[n]+'\"');return t.length?\" \"+t.join(\" \"):\"\"}(t.attrs):\"\")+(t.voidElement?\"/>\":\">\"),t.voidElement?e:e+t.children.reduce(a,\"\")+\"\";case\"comment\":return e+\"\\x3c!--\"+t.comment+\"--\\x3e\"}}var c={parse:function(e,t){t||(t={}),t.components||(t.components=s);var a,c=[],o=[],l=-1,m=!1;if(0!==e.indexOf(\"<\")){var u=e.indexOf(\"<\");c.push({type:\"text\",content:-1===u?e:e.substring(0,u)})}return e.replace(r,function(r,s){if(m){if(r!==\"\")return;m=!1}var u,f=\"/\"!==r.charAt(1),h=r.startsWith(\"\\x3c!--\"),p=s+r.length,d=e.charAt(p);if(h){var v=n(r);return l<0?(c.push(v),c):((u=o[l]).children.push(v),c)}if(f&&(l++,\"tag\"===(a=n(r)).type&&t.components[a.name]&&(a.type=\"component\",m=!0),a.voidElement||m||!d||\"<\"===d||a.children.push({type:\"text\",content:e.slice(p,e.indexOf(\"<\",p))}),0===l&&c.push(a),(u=o[l-1])&&u.children.push(a),o[l]=a),(!f||a.voidElement)&&(l>-1&&(a.voidElement||a.name===r.slice(2,-1))&&(l--,a=-1===l?c:o[l]),!m&&\"<\"!==d&&d)){u=-1===l?c:o[l].children;var x=e.indexOf(\"<\",p),g=e.slice(p,-1===x?void 0:x);i.test(g)&&(g=\" \"),(x>-1&&l+u.length>=0||\" \"!==g)&&u.push({type:\"text\",content:g})}}),c},stringify:function(e){return e.reduce(function(e,t){return e+a(\"\",t)},\"\")}};/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (c);\n//# sourceMappingURL=html-parse-stringify.module.js.map\n\n\n//# sourceURL=webpack://tududi/./node_modules/html-parse-stringify/dist/html-parse-stringify.module.js?"); - -/***/ }), - -/***/ "./node_modules/react-dom/cjs/react-dom.development.js": -/*!*************************************************************!*\ - !*** ./node_modules/react-dom/cjs/react-dom.development.js ***! - \*************************************************************/ -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -"use strict"; -eval("/**\n * @license React\n * react-dom.development.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\n\nif (true) {\n (function() {\n\n 'use strict';\n\n/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\nif (\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart ===\n 'function'\n) {\n __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());\n}\n var React = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\nvar Scheduler = __webpack_require__(/*! scheduler */ \"./node_modules/scheduler/index.js\");\n\nvar ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\nvar suppressWarning = false;\nfunction setSuppressWarning(newSuppressWarning) {\n {\n suppressWarning = newSuppressWarning;\n }\n} // In DEV, calls to console.warn and console.error get replaced\n// by calls to these methods by a Babel plugin.\n//\n// In PROD (or in packages without access to React internals),\n// they are left as they are instead.\n\nfunction warn(format) {\n {\n if (!suppressWarning) {\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n\n printWarning('warn', format, args);\n }\n }\n}\nfunction error(format) {\n {\n if (!suppressWarning) {\n for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n\n printWarning('error', format, args);\n }\n }\n}\n\nfunction printWarning(level, format, args) {\n // When changing this logic, you might want to also\n // update consoleWithStackDev.www.js as well.\n {\n var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n var stack = ReactDebugCurrentFrame.getStackAddendum();\n\n if (stack !== '') {\n format += '%s';\n args = args.concat([stack]);\n } // eslint-disable-next-line react-internal/safe-string-coercion\n\n\n var argsWithFormat = args.map(function (item) {\n return String(item);\n }); // Careful: RN currently depends on this prefix\n\n argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it\n // breaks IE9: https://github.com/facebook/react/issues/13610\n // eslint-disable-next-line react-internal/no-production-logging\n\n Function.prototype.apply.call(console[level], console, argsWithFormat);\n }\n}\n\nvar FunctionComponent = 0;\nvar ClassComponent = 1;\nvar IndeterminateComponent = 2; // Before we know whether it is function or class\n\nvar HostRoot = 3; // Root of a host tree. Could be nested inside another node.\n\nvar HostPortal = 4; // A subtree. Could be an entry point to a different renderer.\n\nvar HostComponent = 5;\nvar HostText = 6;\nvar Fragment = 7;\nvar Mode = 8;\nvar ContextConsumer = 9;\nvar ContextProvider = 10;\nvar ForwardRef = 11;\nvar Profiler = 12;\nvar SuspenseComponent = 13;\nvar MemoComponent = 14;\nvar SimpleMemoComponent = 15;\nvar LazyComponent = 16;\nvar IncompleteClassComponent = 17;\nvar DehydratedFragment = 18;\nvar SuspenseListComponent = 19;\nvar ScopeComponent = 21;\nvar OffscreenComponent = 22;\nvar LegacyHiddenComponent = 23;\nvar CacheComponent = 24;\nvar TracingMarkerComponent = 25;\n\n// -----------------------------------------------------------------------------\n\nvar enableClientRenderFallbackOnTextMismatch = true; // TODO: Need to review this code one more time before landing\n// the react-reconciler package.\n\nvar enableNewReconciler = false; // Support legacy Primer support on internal FB www\n\nvar enableLazyContextPropagation = false; // FB-only usage. The new API has different semantics.\n\nvar enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber\n\nvar enableSuspenseAvoidThisFallback = false; // Enables unstable_avoidThisFallback feature in Fizz\n// React DOM Chopping Block\n//\n// Similar to main Chopping Block but only flags related to React DOM. These are\n// grouped because we will likely batch all of them into a single major release.\n// -----------------------------------------------------------------------------\n// Disable support for comment nodes as React DOM containers. Already disabled\n// in open source, but www codebase still relies on it. Need to remove.\n\nvar disableCommentsAsDOMContainers = true; // Disable javascript: URL strings in href for XSS protection.\n// and client rendering, mostly to allow JSX attributes to apply to the custom\n// element's object properties instead of only HTML attributes.\n// https://github.com/facebook/react/issues/11347\n\nvar enableCustomElementPropertySupport = false; // Disables children for