diff --git a/.gitignore b/.gitignore index 8b6721e..584de4f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .scannerwork/ +.env diff --git a/.paul/ROADMAP.md b/.paul/ROADMAP.md index 3c2d564..0030758 100644 --- a/.paul/ROADMAP.md +++ b/.paul/ROADMAP.md @@ -1,42 +1,43 @@ -# Roadmap: crmPRO +# Roadmap: crmPRO ## Overview -Stabilizacja i poprawa jakości kodu crmPRO — identyfikacja i naprawa błędów, analiza jakości kodu przez SonarQube. +Stabilizacja i poprawa jakosci kodu crmPRO oraz rozwoj finansow o automatyczny import faktur z Fakturowni. ## Current Milestone -**v0.1 Stabilizacja i jakość kodu** (v0.1.0) +**v0.1 Stabilizacja i jakosc kodu + import finansow** (v0.1.0) Status: In progress -Phases: 1 of 4 complete +Phases: 1 of 5 complete ## Phases | Phase | Name | Plans | Status | Completed | |-------|------|-------|--------|-----------| -| 1 | Konfiguracja SonarQube i baseline | 1/1 | ✅ Complete | 2026-03-15 | -| 2 | Naprawa błędów krytycznych | TBD | 🔵 Next | - | -| 3 | Naprawa błędów głównych | TBD | Not started | - | +| 1 | Konfiguracja SonarQube i baseline | 1/1 | Complete | 2026-03-15 | +| 2 | Naprawa bledow krytycznych | TBD | Next | - | +| 3 | Naprawa bledow glownych | TBD | Not started | - | | 4 | Poprawa pokrycia testami | TBD | Not started | - | +| 5 | Import finansow z Fakturowni | 0/1 | Planning | - | ## Phase Details -### Phase 1: Konfiguracja SonarQube i baseline ✅ +### Phase 1: Konfiguracja SonarQube i baseline -**Goal:** Skonfigurować projekt w SonarQube, uruchomić pierwszy skan i uzyskać baseline jakości kodu +**Goal:** Skonfigurowac projekt w SonarQube, uruchomic pierwszy skan i uzyskac baseline jakosci kodu **Depends on:** Nothing (first phase) **Completed:** 2026-03-15 **Results:** - sonar-project.properties skonfigurowany -- Pierwszy skan: 88 plików, 9356 LoC +- Pierwszy skan: 88 plikow, 9356 LoC - Baseline: 58 bugs, 1649 code smells, 0% coverage, 5.6% duplikacji - Reliability: D, Security: A, Maintainability: A **Plans:** -- [x] 01-01: Konfiguracja SonarQube i analiza wyników pierwszego skanu +- [x] 01-01: Konfiguracja SonarQube i analiza wynikow pierwszego skanu -### Phase 2: Naprawa błędów krytycznych +### Phase 2: Naprawa bledow krytycznych -**Goal:** Naprawić wszystkie bugs i vulnerabilities o priorytecie Critical/Blocker +**Goal:** Naprawic wszystkie bugs i vulnerabilities o priorytecie Critical/Blocker **Depends on:** Phase 1 (wyniki skanu) **Research:** Unlikely @@ -46,11 +47,11 @@ Phases: 1 of 4 complete - Reskan po naprawach **Plans:** -- [ ] 02-01: TBD (na podstawie wyników Phase 1) +- [ ] 02-01: TBD (na podstawie wynikow Phase 1) -### Phase 3: Naprawa błędów głównych +### Phase 3: Naprawa bledow glownych -**Goal:** Naprawić bugs o priorytecie Major i code smells wpływające na stabilność +**Goal:** Naprawic bugs o priorytecie Major i code smells wplywajace na stabilnosc **Depends on:** Phase 2 **Research:** Unlikely @@ -60,21 +61,36 @@ Phases: 1 of 4 complete - Reskan po naprawach **Plans:** -- [ ] 03-01: TBD (na podstawie wyników Phase 2) +- [ ] 03-01: TBD (na podstawie wynikow Phase 2) ### Phase 4: Poprawa pokrycia testami -**Goal:** Dodać testy dla kluczowych modułów zidentyfikowanych przez SonarQube +**Goal:** Dodac testy dla kluczowych modulow zidentyfikowanych przez SonarQube **Depends on:** Phase 3 **Research:** Unlikely **Scope:** -- Testy dla modułów o najniższym pokryciu -- Testy regresji dla naprawionych bugów +- Testy dla modulow o najnizszym pokryciu +- Testy regresji dla naprawionych bugow **Plans:** -- [ ] 04-01: TBD (na podstawie wyników Phase 3) +- [ ] 04-01: TBD (na podstawie wynikow Phase 3) + +### Phase 5: Import finansow z Fakturowni + +**Goal:** Wdrozyc automatyczny import faktur przychodowych i kosztowych z Fakturowni do finansow crmPRO +**Depends on:** None (moze byc realizowane niezaleznie od prac SonarQube) +**Research:** Likely (szczegoly endpointow API i semantyka pol dokumentow) + +**Scope:** +- Integracja API Fakturownia (dane z `.env` + data startu importu) +- Trwale mapowanie klientow i produktow/uslug do struktur finansowych CRM +- Import cykliczny przez cron z idempotencja i obsluga bledow +- Panel mapowania brakow w `/finances/main_view/` + +**Plans:** +- [ ] 05-01: Integracja Fakturownia i automatyczny import do finansow --- *Roadmap created: 2026-03-15* -*Last updated: 2026-03-15 — Phase 1 complete* +*Last updated: 2026-04-02 - Phase 5 planned* diff --git a/.paul/STATE.md b/.paul/STATE.md index af23936..bbd1048 100644 --- a/.paul/STATE.md +++ b/.paul/STATE.md @@ -1,57 +1,38 @@ -# Project State +# Project State ## Project Reference See: .paul/PROJECT.md (updated 2026-03-15) -**Core value:** Użytkownicy mogą efektywnie zarządzać projektami, zadaniami i klientami w jednym systemie CRM -**Current focus:** Faza 2 — Naprawa błędów krytycznych +**Core value:** Uzytkownicy moga efektywnie zarzadzac projektami, zadaniami i klientami w jednym systemie CRM +**Current focus:** Faza 5 - Import finansow z Fakturowni ## Current Position -Milestone: v0.1 Stabilizacja i jakość kodu -Phase: 2 of 4 (Naprawa błędów krytycznych) — In Progress -Plan: 02-02 complete, 02-01 awaiting approval -Status: Loop closed for 02-02, ready for next plan -Last activity: 2026-03-15 — Completed .paul/phases/02-critical-bugs-fix/02-02-SUMMARY.md +Milestone: v0.1 Stabilizacja i jakosc kodu +Phase: 5 of 5 (Import finansow z Fakturowni) - Apply complete +Plan: 05-01 executed, awaiting unify +Status: APPLY complete, ready for UNIFY +Last activity: 2026-04-02 11:03 - Executed .paul/phases/05-finances-fakturownia-import/05-01-PLAN.md Progress: -- Milestone: [██░░░░░░░░] 25% -- Phase 2: [█████░░░░░] 50% (1/2 plans complete) +- Milestone: [#######---] 35% +- Phase 5: [########--] 80% ## Loop Position Current loop state: ``` -PLAN ──▶ APPLY ──▶ UNIFY - ✓ ✓ ✓ [Loop complete for 02-02 — ready for next PLAN] +PLAN --> APPLY --> UNIFY + ✓ ✓ ○ [Apply completed, ready for reconciliation] ``` -## Accumulated Context - -### Decisions -- 2026-03-15: SonarQube URL = https://sonar.project-pro.pl (nie localhost) -- 2026-03-15: Skan automatyczny via sonar-scanner CLI + MCP do odczytu wyników -- 2026-03-15: Usunięto nawigację z layout-cron zamiast ukrywania CSS -- 2026-03-15: JSON.parse zamiast deprecated jQuery.parseJSON - -### Deferred Issues -None yet. - -### Blockers/Concerns -None. - -### Git State -Last commit: e92c9fe -Branch: main -Feature branches merged: none - ## Session Continuity -Last session: 2026-03-15 -Stopped at: Plan 02-02 UNIFY complete -Next action: Approve and execute plan 02-01 (SonarQube bugs fix) — run /paul:apply .paul/phases/02-critical-bugs-fix/02-01-PLAN.md -Resume file: .paul/phases/02-critical-bugs-fix/02-02-SUMMARY.md +Last session: 2026-04-02 11:03 +Stopped at: Apply finished for plan 05-01 +Next action: Run $paul-unify .paul/phases/05-finances-fakturownia-import/05-01-PLAN.md +Resume file: .paul/phases/05-finances-fakturownia-import/05-01-PLAN.md --- -*STATE.md — Updated after every significant action* +*STATE.md - Updated after every significant action* diff --git a/.paul/phases/05-finances-fakturownia-import/05-01-PLAN.md b/.paul/phases/05-finances-fakturownia-import/05-01-PLAN.md new file mode 100644 index 0000000..2fbb3c8 --- /dev/null +++ b/.paul/phases/05-finances-fakturownia-import/05-01-PLAN.md @@ -0,0 +1,223 @@ +--- +phase: 05-finances-fakturownia-import +plan: 01 +type: execute +wave: 1 +depends_on: [] +files_modified: + - cron.php + - autoload/class.Cron.php + - autoload/Controllers/FinancesController.php + - autoload/Domain/Finances/FinanceRepository.php + - autoload/Domain/Finances/FakturowniaApiClient.php + - autoload/Domain/Finances/FakturowniaImportRepository.php + - autoload/Domain/Finances/FakturowniaInvoiceImporter.php + - templates/finances/main-view.php + - templates/finances/fakturownia-import-panel.php + - .env.example +autonomous: true +--- + + +## Goal +Dodac automatyczny import faktur przychodowych i kosztowych z Fakturowni do finansow crmPRO, z mechanizmem uczenia mapowan klientow i produktow/uslug. + +## Purpose +Zminimalizowac reczna prace w finansach: pierwsze faktury wymagaja mapowania, ale kolejne dokumenty z tymi samymi klientami i pozycjami maja importowac sie juz calkowicie automatycznie. + +## Output +- Warstwa integracji API Fakturowni z konfiguracja przez `.env` +- Trwale mapowania klientow i produktow/uslug do struktur finansowych crmPRO +- Automatyczny import przez cron z idempotencja i data startu +- Panel w finansach do obslugi brakujacych mapowan + + + +## Project Context +@.paul/PROJECT.md +@.paul/ROADMAP.md +@.paul/STATE.md + +## Source Files +@cron.php +@autoload/class.Cron.php +@autoload/Controllers/FinancesController.php +@autoload/Domain/Finances/FinanceRepository.php +@templates/finances/main-view.php +@config.php + + + + +## AC-1: Konfiguracja API i data startu importu +```gherkin +Given w pliku .env ustawiono dane dostepowe Fakturowni oraz date startu importu +When cron uruchamia proces importu +Then importer laczy sie z API Fakturowni i pobiera tylko dokumenty od skonfigurowanej daty + And brakujaca konfiguracja zwraca czytelny blad bez przerwania calego crona +``` + +## AC-2: Import przychodow i kosztow z idempotencja +```gherkin +Given faktura przychodowa lub kosztowa istnieje w Fakturowni +When dokument ma komplet mapowan klienta i pozycji +Then powstaje operacja finansowa w crmPRO z poprawnym znakiem kwoty (przychod > 0, koszt < 0) + And ponowne uruchomienie importu nie tworzy duplikatu tej samej faktury +``` + +## AC-3: Mechanizm uczenia mapowan +```gherkin +Given dokument zawiera klienta lub pozycje bez mapowania +When importer przetwarza dokument +Then dokument nie jest importowany do finansow, a brakujace mapowania trafiaja na liste do recznego przypisania + And po zapisaniu mapowania kolejne faktury z tym klientem/pozycja importuja sie automatycznie +``` + +## AC-4: Obsluga mapowan w zakladce finansow +```gherkin +Given uzytkownik jest na /finances/main_view/ +When otwiera panel importu Fakturownia +Then widzi brakujace mapowania klientow i produktow/uslug + And moze przypisac klienta CRM i kategorie finansowa + And zapis mapowania jest chroniony tokenem CSRF +``` + + + + + + + Task 1: Zbudowac warstwe integracji Fakturownia + trwawe mapowania + + autoload/Domain/Finances/FakturowniaApiClient.php, + autoload/Domain/Finances/FakturowniaImportRepository.php, + autoload/Domain/Finances/FinanceRepository.php, + .env.example + + + 1. Dodac loader `.env` (bez nowych bibliotek) i zdefiniowac klucze: + - `FAKTUROWNIA_API_DOMAIN` + - `FAKTUROWNIA_API_TOKEN` + - `FAKTUROWNIA_START_DATE` + - `FAKTUROWNIA_PAGE_LIMIT` (opcjonalnie) + 2. Dodac klienta API Fakturowni z obsluga paginacji i timeoutow: + - pobieranie faktur przychodowych (np. endpoint invoices) + - pobieranie faktur kosztowych (np. endpoint costs/expenses) + 3. Dodac repozytorium importu z tabelami tworzonymi przez `CREATE TABLE IF NOT EXISTS`: + - tabela mapowania klientow Fakturownia -> crm_client.id + - tabela mapowania pozycji (nazwa produktu/uslugi) -> finance_categories.id + - tabela stanu importu i idempotencji (external_id + typ dokumentu) + - tabela kolejki brakujacych mapowan do panelu finansow + 4. Wszystkie zapytania SQL wykonywac przez medoo/query z parametrami bindowanymi (bez sklejania SQL z danymi wejsciowymi). + 5. W `FinanceRepository` dodac metody pomocnicze do pobierania kategorii i klientow dla panelu mapowan. + + Unikac: trzymania tokenu API w `config.php`, mapowan w sesji i importu bez kontroli duplikatow. + + + - Odczyt `.env.example` potwierdza nowe klucze integracji. + - Odczyt nowych klas potwierdza osobne odpowiedzialnosci (API, repo mapowan, state importu). + - Test manualny: dwukrotne wywolanie zapisu importu dla tego samego external_id nie tworzy duplikatu. + + AC-1 i AC-2 i AC-3 satisfied: konfiguracja, idempotencja i struktury mapowan gotowe + + + + Task 2: Dodac importer dokumentow i podpiac go pod cron + + autoload/Domain/Finances/FakturowniaInvoiceImporter.php, + autoload/class.Cron.php, + cron.php + + + 1. Dodac serwis importera, ktory: + - pobiera dokumenty od `FAKTUROWNIA_START_DATE`, + - scala dane klienta i pozycji, + - sprawdza mapowania klienta i pozycji, + - przy komplecie mapowan zapisuje operacje finansowe, + - przy brakach wpisuje rekordy do kolejki brakow mapowan i pomija import dokumentu. + 2. Dodac polityke znaku kwoty: + - przychodowe -> dodatnie `amount` + - kosztowe -> ujemne `amount` + 3. Wprowadzic idempotencje na poziomie zrodlowego `external_id` + typ dokumentu. + 4. Rozszerzyc `Cron` i `cron.php` o krok `import_finances_from_fakturownia()`: + - uruchamiany przy kazdym cyklu crona, + - zwraca statusy `ok|empty|error` analogicznie do obecnych zadan, + - loguje krotki komunikat o liczbie zaimportowanych i pominietych dokumentow. + + Unikac: przerywania calego crona przy pojedynczym bledzie faktury. + + + - Suchy przebieg importera zwraca licznik imported/skipped/unmapped. + - Uruchomienie `php cron.php` wykonuje nowy krok i nie psuje istniejacych zadan cron. + - Powtorne uruchomienie dla tych samych danych nie dubluje wpisow w `finance_operations`. + + AC-1 i AC-2 i AC-3 satisfied: cron importuje faktury cyklicznie i bez duplikatow + + + + Task 3: Dodac panel mapowan Fakturowni w finansach i zapis mapowan + + autoload/Controllers/FinancesController.php, + templates/finances/main-view.php, + templates/finances/fakturownia-import-panel.php + + + 1. Rozszerzyc `FinancesController` o akcje: + - pobranie brakujacych mapowan do widoku finansow, + - zapis mapowania klienta, + - zapis mapowania produktu/uslugi do kategorii, + - wszystkie zapisy z walidacja i `S::csrf_verify()`. + 2. W `templates/finances/main-view.php` dolaczyc panel importu (partial) pokazujacy: + - liste nieprzypisanych klientow z Fakturowni + select klienta CRM, + - liste nieprzypisanych pozycji + select kategorii finansowej, + - status ostatniego importu (czas, liczba imported/skipped/unmapped). + 3. W panelu uzyc escapingu danych wyjsciowych (np. `htmlspecialchars`) i komunikatow zgodnych z UI crmPRO. + + Unikac: logiki biznesowej bezposrednio w widoku. + + + - Wejscie na `/finances/main_view/` pokazuje panel mapowan bez regresji istniejacych statystyk. + - Zapis mapowania bez tokenu CSRF jest odrzucany. + - Po zapisaniu mapowania i ponownym imporcie dokument znika z listy brakow i tworzy operacje automatycznie. + + AC-3 i AC-4 satisfied: mapowania sa obslugiwane z UI i kolejne faktury wpadaja automatycznie + + + + + + +## DO NOT CHANGE +- modules niezwiązane z finansami (tasks, projects, wiki) +- mechanizm logowania i sesji poza niezbednym CSRF check +- istniejace endpointy email importera zadan + +## SCOPE LIMITS +- Ten plan obejmuje tylko import i mapowania Fakturownia -> Finanse +- Bez refaktoryzacji calego modulu finansow +- Bez zmian w zewnetrznym harmonogramie systemowym (zakladamy, ze cron systemowy juz wywoluje `cron.php`) +- Bez automatycznego tworzenia nowych klientow CRM (tylko mapowanie do istniejacych) + + + + +Before declaring plan complete: +- [ ] `.env.example` zawiera komplet nowych zmiennych Fakturowni +- [ ] Importer obsluguje dokumenty przychodowe i kosztowe +- [ ] Idempotencja blokuje duplikaty importu +- [ ] Brakujace mapowania sa kolejkowane i widoczne w finansach +- [ ] Zapis mapowan wymaga poprawnego tokenu CSRF +- [ ] `php cron.php` wykonuje import bez zatrzymywania pozostalych krokow +- [ ] All acceptance criteria met + + + +- Faktury przychodowe i kosztowe importuja sie automatycznie po uzupelnieniu mapowan +- Pierwszy import nie robi blednych przypisan: nieznane rekordy trafiaja do kolejki mapowania +- Kolejne dokumenty z tym samym klientem i pozycja sa przypisywane bez interwencji recznej +- Import uruchamia sie cyklicznie przez cron i jest bezpieczny na ponowne wykonanie + + + +After completion, create `.paul/phases/05-finances-fakturownia-import/05-01-SUMMARY.md` + diff --git a/.vscode/ftp-kr.sync.cache.json b/.vscode/ftp-kr.sync.cache.json index b5893c6..d5fbc20 100644 --- a/.vscode/ftp-kr.sync.cache.json +++ b/.vscode/ftp-kr.sync.cache.json @@ -681,8 +681,8 @@ }, "main_view.php": { "type": "-", - "size": 47213, - "lmtime": 1773530856493, + "size": 49131, + "lmtime": 1774532986644, "modified": false }, "task_edit.php": { @@ -693,9 +693,9 @@ }, "task_popup.php": { "type": "-", - "size": 42366, + "size": 45012, "lmtime": 1773530848546, - "modified": false + "modified": true }, "task_single.php": { "type": "-", @@ -703,11 +703,17 @@ "lmtime": 1772276304856, "modified": false }, + "task_work_logs_popup.php": { + "type": "-", + "size": 2629, + "lmtime": 0, + "modified": false + }, "work-time.php": { "type": "-", - "size": 12763, + "size": 15966, "lmtime": 1771236164971, - "modified": false + "modified": true } }, "users": { diff --git a/__tmp_count.php b/__tmp_count.php new file mode 100644 index 0000000..2f06d81 --- /dev/null +++ b/__tmp_count.php @@ -0,0 +1,47 @@ += strtotime($start) && (($doc['income'] ?? true) !== false)) $sf[] = $doc; +} + +$cf = []; +foreach ($costs as $doc) { + $date = normalizeDate($doc); + if ($date && strtotime($date) >= strtotime($start)) $cf[] = $doc; +} + +echo 'sales_from_start(issue_date_first)=' . count($sf) . PHP_EOL; +echo 'costs_from_start(issue_date_first)=' . count($cf) . PHP_EOL; diff --git a/__tmp_diag.php b/__tmp_diag.php new file mode 100644 index 0000000..39086ff --- /dev/null +++ b/__tmp_diag.php @@ -0,0 +1,54 @@ += strtotime($start)) $sf[] = $doc; +} + +$cf = []; +foreach ($costs as $doc) { + $date = isset($doc['sell_date']) && $doc['sell_date'] ? $doc['sell_date'] : (isset($doc['issue_date']) ? $doc['issue_date'] : ''); + if ($date && strtotime(substr($date,0,10)) >= strtotime($start)) $cf[] = $doc; +} + +echo 'sales_all=' . count($sales) . PHP_EOL; +echo 'costs_all=' . count($costs) . PHP_EOL; +echo 'sales_from_start=' . count($sf) . PHP_EOL; +echo 'costs_from_start=' . count($cf) . PHP_EOL; + +echo "-- sales_from_start --" . PHP_EOL; +foreach ($sf as $d) { + echo $d['id'] . ' | ' . ($d['number'] ?? '-') . ' | ' . ($d['sell_date'] ?? '-') . ' | ' . ($d['issue_date'] ?? '-') . PHP_EOL; +} + +echo "-- costs_from_start --" . PHP_EOL; +foreach ($cf as $d) { + echo $d['id'] . ' | ' . ($d['number'] ?? '-') . ' | ' . ($d['sell_date'] ?? '-') . ' | ' . ($d['issue_date'] ?? '-') . PHP_EOL; +} diff --git a/autoload/Controllers/FinancesController.php b/autoload/Controllers/FinancesController.php index 6c5c0f1..82ee9d3 100644 --- a/autoload/Controllers/FinancesController.php +++ b/autoload/Controllers/FinancesController.php @@ -8,6 +8,11 @@ class FinancesController return new \Domain\Finances\FinanceRepository(); } + private static function importRepo() + { + return new \Domain\Finances\FakturowniaImportRepository(); + } + private static function requireAuth() { global $user; @@ -53,6 +58,8 @@ class FinancesController return false; $repo = self::repo(); + $importRepo = self::importRepo(); + $importRepo -> ensureTables(); if ( \S::get( 'tag-clear' ) ) unset( $_SESSION['finance-tag-id'] ); @@ -93,10 +100,121 @@ class FinancesController 'wallet_summary' => $repo -> walletSummary( $group_id ), 'wallet_summary_this_month' => $repo -> walletSummaryThisMonth( $group_id ), 'wallet_income_this_month' => $repo -> walletIncomeThisMonth( $group_id ), - 'wallet_expenses_this_month' => $repo -> walletExpensesThisMonth( $group_id ) + 'wallet_expenses_this_month' => $repo -> walletExpensesThisMonth( $group_id ), + 'fakturownia_pending_clients' => self::preparePendingRows( $importRepo -> pendingClientMappings() ), + 'fakturownia_pending_items' => self::preparePendingRows( $importRepo -> pendingItemMappings() ), + 'fakturownia_crm_clients' => $repo -> clientsList(), + 'fakturownia_categories' => self::prepareCategoryOptions( $repo -> categoriesFlatList() ), + 'fakturownia_last_summary' => self::lastImportSummary( $importRepo ) ] ); } + private static function preparePendingRows( $rows ) + { + $output = []; + + if ( !is_array( $rows ) ) + return $output; + + foreach ( $rows as $row ) + { + $payload = []; + if ( isset( $row['payload_json'] ) && $row['payload_json'] ) + { + $decoded = json_decode( $row['payload_json'], true ); + if ( is_array( $decoded ) ) + $payload = $decoded; + } + + $output[] = [ + 'external_key' => (string)$row['external_key'], + 'external_name' => (string)$row['external_name'], + 'hits' => (int)$row['hits'], + 'last_seen_at' => (string)$row['last_seen_at'], + 'payload' => $payload + ]; + } + + return $output; + } + + private static function lastImportSummary( $importRepo ) + { + $raw = $importRepo -> getState( 'last_import_summary' ); + if ( !$raw ) + return null; + + $decoded = json_decode( $raw, true ); + return is_array( $decoded ) ? $decoded : null; + } + + private static function prepareCategoryOptions( $categories ) + { + $options = []; + if ( !is_array( $categories ) || empty( $categories ) ) + return $options; + + $byId = []; + foreach ( $categories as $category ) + { + $id = isset( $category['id'] ) ? (int)$category['id'] : 0; + if ( $id <= 0 ) + continue; + + $byId[ $id ] = $category; + } + + foreach ( $categories as $category ) + { + $id = isset( $category['id'] ) ? (int)$category['id'] : 0; + if ( $id <= 0 ) + continue; + + $label = self::buildCategoryPathLabel( $id, $byId ); + $options[] = [ + 'id' => $id, + 'name' => $label, + 'group_id' => isset( $category['group_id'] ) ? (int)$category['group_id'] : 0 + ]; + } + + usort( $options, function( $left, $right ) + { + return strcmp( $left['name'], $right['name'] ); + } ); + + return $options; + } + + private static function buildCategoryPathLabel( $categoryId, $byId ) + { + $parts = []; + $guard = 0; + $currentId = (int)$categoryId; + + while ( $currentId > 0 && isset( $byId[ $currentId ] ) ) + { + $category = $byId[ $currentId ]; + $name = trim( (string)( $category['name'] ?? '' ) ); + if ( $name !== '' ) + array_unshift( $parts, $name ); + + $parentId = isset( $category['parent_id'] ) ? (int)$category['parent_id'] : 0; + if ( $parentId <= 0 || $parentId === $currentId ) + break; + + $currentId = $parentId; + $guard++; + if ( $guard > 20 ) + break; + } + + if ( empty( $parts ) ) + return 'Kategoria #' . (int)$categoryId; + + return implode( ' > ', $parts ); + } + public static function operationEdit() { if ( !self::requireAuth() ) @@ -230,4 +348,70 @@ class FinancesController 'date_to' => $date_to ] ); } + + public static function fakturowniaClientMappingSave() + { + if ( !self::requireAuth() ) + return false; + + if ( !\S::csrf_verify() ) + { + \S::alert( 'Nieprawidlowy token bezpieczenstwa. Odswiez strone i sproboj ponownie.' ); + header( 'Location: /finances/main_view/' ); + exit; + } + + $externalKey = trim( (string)\S::get( 'external_key' ) ); + $externalName = trim( (string)\S::get( 'external_name' ) ); + $crmClientId = (int)\S::get( 'crm_client_id' ); + $repo = self::repo(); + + if ( $externalKey === '' || $externalName === '' || $crmClientId <= 0 || !$repo -> clientExists( $crmClientId ) ) + { + \S::alert( 'Nie udalo sie zapisac mapowania klienta. Uzupelnij wszystkie pola.' ); + header( 'Location: /finances/main_view/' ); + exit; + } + + $importRepo = self::importRepo(); + $importRepo -> ensureTables(); + $importRepo -> saveClientMapping( $externalKey, $externalName, $crmClientId ); + + \S::alert( 'Mapowanie klienta zostalo zapisane.' ); + header( 'Location: /finances/main_view/' ); + exit; + } + + public static function fakturowniaItemMappingSave() + { + if ( !self::requireAuth() ) + return false; + + if ( !\S::csrf_verify() ) + { + \S::alert( 'Nieprawidlowy token bezpieczenstwa. Odswiez strone i sproboj ponownie.' ); + header( 'Location: /finances/main_view/' ); + exit; + } + + $externalKey = trim( (string)\S::get( 'external_key' ) ); + $externalName = trim( (string)\S::get( 'external_name' ) ); + $financeCategoryId = (int)\S::get( 'finance_category_id' ); + $repo = self::repo(); + + if ( $externalKey === '' || $externalName === '' || $financeCategoryId <= 0 || !$repo -> categoryExists( $financeCategoryId ) ) + { + \S::alert( 'Nie udalo sie zapisac mapowania pozycji. Uzupelnij wszystkie pola.' ); + header( 'Location: /finances/main_view/' ); + exit; + } + + $importRepo = self::importRepo(); + $importRepo -> ensureTables(); + $importRepo -> saveItemMapping( $externalKey, $externalName, $financeCategoryId ); + + \S::alert( 'Mapowanie pozycji zostalo zapisane.' ); + header( 'Location: /finances/main_view/' ); + exit; + } } diff --git a/autoload/Domain/Finances/FakturowniaApiClient.php b/autoload/Domain/Finances/FakturowniaApiClient.php new file mode 100644 index 0000000..4d4365e --- /dev/null +++ b/autoload/Domain/Finances/FakturowniaApiClient.php @@ -0,0 +1,162 @@ + baseUrl = rtrim( (string)$baseUrl, '/' ); + $this -> apiToken = (string)$apiToken; + $this -> pageLimit = max( 1, (int)$pageLimit ); + $this -> timeout = max( 5, (int)$timeout ); + } + + public function fetchSalesDocuments( $startDate, $page = 1 ) + { + $query = [ + 'page' => (int)$page, + 'per_page' => $this -> pageLimit + ]; + + if ( $this -> canUseCurrentMonthPeriod( $startDate ) ) + $query['period'] = 'this_month'; + + return $this -> requestList( '/invoices.json', $query ); + } + + public function fetchCostDocuments( $startDate, $page = 1 ) + { + $queries = [ + [ + 'page' => (int)$page, + 'per_page' => $this -> pageLimit, + 'income' => 'no' + ] + ]; + + if ( $this -> canUseCurrentMonthPeriod( $startDate ) ) + $queries[0]['period'] = 'this_month'; + + $paths = [ '/costs.json', '/expenses.json', '/invoices.json' ]; + + foreach ( $paths as $path ) + { + foreach ( $queries as $query ) + { + $response = $this -> requestList( $path, $query, true ); + if ( $response['ok'] ) + return $response['data']; + } + } + + throw new \RuntimeException( 'Nie udalo sie pobrac faktur kosztowych z API Fakturowni.' ); + } + + public function fetchInvoiceDetails( $invoiceId ) + { + $invoiceId = (int)$invoiceId; + if ( $invoiceId <= 0 ) + return null; + + $result = $this -> request( '/invoices/' . $invoiceId . '.json', [] ); + if ( $result['http_code'] >= 400 ) + return null; + + $data = json_decode( $result['body'], true ); + return is_array( $data ) ? $data : null; + } + + private function requestList( $path, $query, $softFail = false ) + { + $result = $this -> request( $path, $query ); + + if ( $result['http_code'] >= 400 ) + { + if ( $softFail ) + return [ 'ok' => false, 'data' => [] ]; + + throw new \RuntimeException( 'Blad API Fakturowni: HTTP ' . $result['http_code'] . ' dla ' . $path ); + } + + $data = json_decode( $result['body'], true ); + if ( !is_array( $data ) ) + { + if ( $softFail ) + return [ 'ok' => false, 'data' => [] ]; + + throw new \RuntimeException( 'API Fakturowni zwrocilo niepoprawny JSON.' ); + } + + $list = $this -> extractList( $data ); + return $softFail ? [ 'ok' => true, 'data' => $list ] : $list; + } + + private function request( $path, $query ) + { + $query['api_token'] = $this -> apiToken; + $url = $this -> baseUrl . $path . '?' . http_build_query( $query ); + + $ch = curl_init( $url ); + curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); + curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, $this -> timeout ); + curl_setopt( $ch, CURLOPT_TIMEOUT, $this -> timeout ); + curl_setopt( $ch, CURLOPT_HTTPHEADER, [ + 'Accept: application/json' + ] ); + + $body = curl_exec( $ch ); + $httpCode = (int)curl_getinfo( $ch, CURLINFO_HTTP_CODE ); + $error = curl_error( $ch ); + curl_close( $ch ); + + if ( $body === false ) + throw new \RuntimeException( 'Blad polaczenia z API Fakturowni: ' . $error ); + + return [ + 'http_code' => $httpCode, + 'body' => $body + ]; + } + + private function extractList( $data ) + { + if ( $this -> isList( $data ) ) + return $data; + + $keys = [ 'invoices', 'costs', 'expenses', 'data' ]; + foreach ( $keys as $key ) + { + if ( isset( $data[ $key ] ) && is_array( $data[ $key ] ) ) + { + if ( $this -> isList( $data[ $key ] ) ) + return $data[ $key ]; + } + } + + return []; + } + + private function isList( $value ) + { + if ( !is_array( $value ) ) + return false; + + if ( $value === [] ) + return true; + + return array_keys( $value ) === range( 0, count( $value ) - 1 ); + } + + private function canUseCurrentMonthPeriod( $startDate ) + { + if ( !is_string( $startDate ) || !preg_match( '/^\d{4}-\d{2}-\d{2}$/', $startDate ) ) + return false; + + return $startDate === date( 'Y-m-01' ); + } +} diff --git a/autoload/Domain/Finances/FakturowniaImportRepository.php b/autoload/Domain/Finances/FakturowniaImportRepository.php new file mode 100644 index 0000000..6553f26 --- /dev/null +++ b/autoload/Domain/Finances/FakturowniaImportRepository.php @@ -0,0 +1,318 @@ + mdb = $mdb; + else + { + global $mdb; + $this -> mdb = $mdb; + } + } + + public function ensureTables() + { + if ( $this -> tablesReady ) + return; + + $this -> mdb -> query( + 'CREATE TABLE IF NOT EXISTS `fakturownia_client_mappings` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `external_client_key` VARCHAR(191) NOT NULL, + `external_name` VARCHAR(255) NOT NULL, + `crm_client_id` INT UNSIGNED NOT NULL, + `created_at` DATETIME NOT NULL, + `updated_at` DATETIME NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_external_client_key` (`external_client_key`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8' + ); + + $this -> mdb -> query( + 'CREATE TABLE IF NOT EXISTS `fakturownia_item_mappings` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `external_item_key` VARCHAR(191) NOT NULL, + `external_name` VARCHAR(255) NOT NULL, + `finance_category_id` INT UNSIGNED NOT NULL, + `created_at` DATETIME NOT NULL, + `updated_at` DATETIME NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_external_item_key` (`external_item_key`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8' + ); + + $this -> mdb -> query( + 'CREATE TABLE IF NOT EXISTS `fakturownia_imported_documents` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `external_document_key` VARCHAR(191) NOT NULL, + `document_type` VARCHAR(32) NOT NULL, + `external_id` VARCHAR(64) NOT NULL, + `source_date` DATE NULL, + `amount` DECIMAL(12,2) NOT NULL DEFAULT 0.00, + `finance_operation_ids` TEXT NULL, + `meta_json` LONGTEXT NULL, + `imported_at` DATETIME NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_external_document_key` (`external_document_key`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8' + ); + + $this -> mdb -> query( + 'CREATE TABLE IF NOT EXISTS `fakturownia_unmapped_queue` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `queue_type` VARCHAR(32) NOT NULL, + `external_key` VARCHAR(191) NOT NULL, + `external_name` VARCHAR(255) NOT NULL, + `payload_json` LONGTEXT NULL, + `hits` INT UNSIGNED NOT NULL DEFAULT 1, + `resolved` TINYINT(1) NOT NULL DEFAULT 0, + `first_seen_at` DATETIME NOT NULL, + `last_seen_at` DATETIME NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_type_key` (`queue_type`, `external_key`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8' + ); + + $this -> mdb -> query( + 'CREATE TABLE IF NOT EXISTS `fakturownia_import_state` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `state_key` VARCHAR(191) NOT NULL, + `state_value` LONGTEXT NULL, + `updated_at` DATETIME NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_state_key` (`state_key`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8' + ); + + $this -> tablesReady = true; + } + + public function getClientMapping( $externalClientKey ) + { + $this -> ensureTables(); + return $this -> mdb -> get( 'fakturownia_client_mappings', '*', [ + 'external_client_key' => $externalClientKey + ] ); + } + + public function saveClientMapping( $externalClientKey, $externalName, $crmClientId ) + { + $this -> ensureTables(); + + $current = $this -> getClientMapping( $externalClientKey ); + $now = date( 'Y-m-d H:i:s' ); + + if ( $current ) + { + $this -> mdb -> update( 'fakturownia_client_mappings', [ + 'external_name' => $externalName, + 'crm_client_id' => (int)$crmClientId, + 'updated_at' => $now + ], [ 'id' => (int)$current['id'] ] ); + } + else + { + $this -> mdb -> insert( 'fakturownia_client_mappings', [ + 'external_client_key' => $externalClientKey, + 'external_name' => $externalName, + 'crm_client_id' => (int)$crmClientId, + 'created_at' => $now, + 'updated_at' => $now + ] ); + } + + $this -> resolveQueueItem( 'client', $externalClientKey ); + } + + public function getItemMapping( $externalItemKey ) + { + $this -> ensureTables(); + return $this -> mdb -> get( 'fakturownia_item_mappings', '*', [ + 'external_item_key' => $externalItemKey + ] ); + } + + public function saveItemMapping( $externalItemKey, $externalName, $financeCategoryId ) + { + $this -> ensureTables(); + + $current = $this -> getItemMapping( $externalItemKey ); + $now = date( 'Y-m-d H:i:s' ); + + if ( $current ) + { + $this -> mdb -> update( 'fakturownia_item_mappings', [ + 'external_name' => $externalName, + 'finance_category_id' => (int)$financeCategoryId, + 'updated_at' => $now + ], [ 'id' => (int)$current['id'] ] ); + } + else + { + $this -> mdb -> insert( 'fakturownia_item_mappings', [ + 'external_item_key' => $externalItemKey, + 'external_name' => $externalName, + 'finance_category_id' => (int)$financeCategoryId, + 'created_at' => $now, + 'updated_at' => $now + ] ); + } + + $this -> resolveQueueItem( 'item', $externalItemKey ); + } + + public function isDocumentImported( $externalDocumentKey ) + { + $this -> ensureTables(); + return (bool)$this -> mdb -> has( 'fakturownia_imported_documents', [ + 'external_document_key' => $externalDocumentKey + ] ); + } + + public function markDocumentImported( $externalDocumentKey, $documentType, $externalId, $sourceDate, $amount, $operationIds, $meta ) + { + $this -> ensureTables(); + + $now = date( 'Y-m-d H:i:s' ); + $data = [ + 'external_document_key' => $externalDocumentKey, + 'document_type' => $documentType, + 'external_id' => (string)$externalId, + 'source_date' => $sourceDate, + 'amount' => (float)$amount, + 'finance_operation_ids' => implode( ',', $operationIds ), + 'meta_json' => json_encode( $meta, JSON_UNESCAPED_UNICODE ), + 'imported_at' => $now + ]; + + $existing = $this -> mdb -> get( 'fakturownia_imported_documents', 'id', [ + 'external_document_key' => $externalDocumentKey + ] ); + + if ( $existing ) + { + $this -> mdb -> update( 'fakturownia_imported_documents', $data, [ + 'id' => (int)$existing + ] ); + return; + } + + $this -> mdb -> insert( 'fakturownia_imported_documents', $data ); + } + + public function queueUnmapped( $queueType, $externalKey, $externalName, $payload ) + { + $this -> ensureTables(); + + $existing = $this -> mdb -> get( 'fakturownia_unmapped_queue', '*', [ + 'AND' => [ + 'queue_type' => $queueType, + 'external_key' => $externalKey + ] + ] ); + + $now = date( 'Y-m-d H:i:s' ); + $payloadJson = json_encode( $payload, JSON_UNESCAPED_UNICODE ); + + if ( $existing ) + { + $this -> mdb -> update( 'fakturownia_unmapped_queue', [ + 'external_name' => $externalName, + 'payload_json' => $payloadJson, + 'hits[+]' => 1, + 'resolved' => 0, + 'last_seen_at' => $now + ], [ 'id' => (int)$existing['id'] ] ); + return; + } + + $this -> mdb -> insert( 'fakturownia_unmapped_queue', [ + 'queue_type' => $queueType, + 'external_key' => $externalKey, + 'external_name' => $externalName, + 'payload_json' => $payloadJson, + 'hits' => 1, + 'resolved' => 0, + 'first_seen_at' => $now, + 'last_seen_at' => $now + ] ); + } + + public function pendingClientMappings() + { + $this -> ensureTables(); + return $this -> mdb -> select( 'fakturownia_unmapped_queue', '*', [ + 'AND' => [ + 'queue_type' => 'client', + 'resolved' => 0 + ], + 'ORDER' => [ 'last_seen_at' => 'DESC' ] + ] ); + } + + public function pendingItemMappings() + { + $this -> ensureTables(); + return $this -> mdb -> select( 'fakturownia_unmapped_queue', '*', [ + 'AND' => [ + 'queue_type' => 'item', + 'resolved' => 0, + 'external_key[!]' => 'name:faktura bez pozycji' + ], + 'ORDER' => [ 'last_seen_at' => 'DESC' ] + ] ); + } + + public function saveState( $stateKey, $stateValue ) + { + $this -> ensureTables(); + + $existing = $this -> mdb -> get( 'fakturownia_import_state', '*', [ + 'state_key' => $stateKey + ] ); + $now = date( 'Y-m-d H:i:s' ); + + if ( $existing ) + { + $this -> mdb -> update( 'fakturownia_import_state', [ + 'state_value' => $stateValue, + 'updated_at' => $now + ], [ 'id' => (int)$existing['id'] ] ); + return; + } + + $this -> mdb -> insert( 'fakturownia_import_state', [ + 'state_key' => $stateKey, + 'state_value' => $stateValue, + 'updated_at' => $now + ] ); + } + + public function getState( $stateKey ) + { + $this -> ensureTables(); + return $this -> mdb -> get( 'fakturownia_import_state', 'state_value', [ + 'state_key' => $stateKey + ] ); + } + + private function resolveQueueItem( $queueType, $externalKey ) + { + $this -> mdb -> update( 'fakturownia_unmapped_queue', [ + 'resolved' => 1, + 'last_seen_at' => date( 'Y-m-d H:i:s' ) + ], [ + 'AND' => [ + 'queue_type' => $queueType, + 'external_key' => $externalKey + ] + ] ); + } +} diff --git a/autoload/Domain/Finances/FakturowniaInvoiceImporter.php b/autoload/Domain/Finances/FakturowniaInvoiceImporter.php new file mode 100644 index 0000000..fe79ba9 --- /dev/null +++ b/autoload/Domain/Finances/FakturowniaInvoiceImporter.php @@ -0,0 +1,461 @@ + mdb = $mdb; + else + { + global $mdb; + $this -> mdb = $mdb; + } + + $this -> repo = new FakturowniaImportRepository( $this -> mdb ); + } + + public function import() + { + $this -> repo -> ensureTables(); + + $config = $this -> resolveConfig(); + if ( !$config['ok'] ) + return $config; + + $this -> startDate = $config['start_date']; + $this -> apiClient = new FakturowniaApiClient( + $config['api_url'], + $config['token'], + $config['page_limit'] + ); + $this -> pageLimit = (int)$config['page_limit']; + + $summary = [ + 'imported' => 0, + 'skipped' => 0, + 'unmapped' => 0, + 'errors' => 0 + ]; + + $summary = $this -> processDocumentType( 'income', $summary ); + $summary = $this -> processDocumentType( 'cost', $summary ); + + $lastSummary = json_encode( [ + 'at' => date( 'Y-m-d H:i:s' ), + 'summary' => $summary + ], JSON_UNESCAPED_UNICODE ); + $this -> repo -> saveState( 'last_import_summary', $lastSummary ); + + if ( $summary['imported'] === 0 && $summary['unmapped'] === 0 && $summary['errors'] === 0 ) + return [ 'status' => 'empty', 'msg' => 'Import Fakturownia: brak nowych dokumentow.' ]; + + if ( $summary['errors'] > 0 ) + return [ 'status' => 'error', 'msg' => $this -> formatMessage( $summary ), 'summary' => $summary ]; + + return [ 'status' => 'ok', 'msg' => $this -> formatMessage( $summary ), 'summary' => $summary ]; + } + + private function processDocumentType( $documentType, $summary ) + { + $page = 1; + + while ( true ) + { + try + { + if ( $documentType === 'income' ) + $documents = $this -> apiClient -> fetchSalesDocuments( $this -> startDate, $page ); + else + $documents = $this -> apiClient -> fetchCostDocuments( $this -> startDate, $page ); + } + catch ( \Throwable $e ) + { + $summary['errors']++; + break; + } + + if ( !is_array( $documents ) || empty( $documents ) ) + break; + + $hasRelevantDateInPage = false; + + foreach ( $documents as $document ) + { + if ( $this -> isDateRelevantForImport( $document ) ) + $hasRelevantDateInPage = true; + + $result = $this -> processSingleDocument( $document, $documentType ); + $summary[ $result ]++; + } + + if ( count( $documents ) < $this -> pageLimit ) + break; + + // API zwraca dokumenty malejaco po czasie. Gdy cala strona jest starsza niz startDate, + // kolejne strony tez beda starsze i nie ma sensu pobierac dalej. + if ( !$hasRelevantDateInPage ) + break; + + $page++; + if ( $page > 100 ) + break; + } + + return $summary; + } + + private function processSingleDocument( $rawDocument, $documentType ) + { + if ( !$this -> matchesDocumentType( $rawDocument, $documentType ) ) + return 'skipped'; + + $document = $this -> normalizeDocument( $rawDocument, $documentType ); + if ( !$document ) + return 'skipped'; + + if ( $this -> repo -> isDocumentImported( $document['document_key'] ) ) + return 'skipped'; + + if ( strtotime( $document['date'] ) < strtotime( $this -> startDate ) ) + return 'skipped'; + + $clientMap = $this -> repo -> getClientMapping( $document['client_key'] ); + if ( !$clientMap ) + { + $this -> repo -> queueUnmapped( 'client', $document['client_key'], $document['client_name'], [ + 'document_id' => $document['external_id'], + 'document_number' => $document['number'], + 'document_type' => $documentType, + 'tax_no' => $document['client_tax_no'] + ] ); + return 'unmapped'; + } + + $resolvedPositions = []; + foreach ( $document['positions'] as $position ) + { + $itemMap = $this -> repo -> getItemMapping( $position['item_key'] ); + if ( !$itemMap ) + { + $this -> repo -> queueUnmapped( 'item', $position['item_key'], $position['name'], [ + 'document_id' => $document['external_id'], + 'document_number' => $document['number'], + 'document_type' => $documentType + ] ); + return 'unmapped'; + } + + $amount = $this -> normalizeAmount( $position['amount'], $documentType ); + if ( $amount == 0.0 ) + continue; + + $resolvedPositions[] = [ + 'category_id' => (int)$itemMap['finance_category_id'], + 'amount' => $amount, + 'description' => $this -> buildDescription( $document, $position ) + ]; + } + + if ( empty( $resolvedPositions ) ) + return 'skipped'; + + $operationIds = []; + + // Cala faktura importuje sie atomowo: albo wszystkie pozycje, albo nic. + $this -> mdb -> pdo -> beginTransaction(); + try + { + foreach ( $resolvedPositions as $resolvedPosition ) + { + $this -> mdb -> insert( 'finance_operations', [ + 'date' => $document['date'], + 'category_id' => $resolvedPosition['category_id'], + 'amount' => $resolvedPosition['amount'], + 'description' => $resolvedPosition['description'], + 'client_id' => (int)$clientMap['crm_client_id'] + ] ); + + $operationIds[] = (int)$this -> mdb -> id(); + } + + $this -> repo -> markDocumentImported( + $document['document_key'], + $documentType, + $document['external_id'], + $document['date'], + $document['total_amount'], + $operationIds, + [ + 'number' => $document['number'], + 'client_name' => $document['client_name'] + ] + ); + + $this -> mdb -> pdo -> commit(); + } + catch ( \Throwable $e ) + { + if ( $this -> mdb -> pdo ->inTransaction() ) + $this -> mdb -> pdo -> rollBack(); + + throw $e; + } + + return 'imported'; + } + + private function matchesDocumentType( $rawDocument, $documentType ) + { + if ( isset( $rawDocument['invoice'] ) && is_array( $rawDocument['invoice'] ) ) + $rawDocument = $rawDocument['invoice']; + + if ( !is_array( $rawDocument ) ) + return false; + + if ( !array_key_exists( 'income', $rawDocument ) ) + return true; + + $incomeFlag = $rawDocument['income']; + $isIncome = !in_array( $incomeFlag, [ false, 0, '0', 'false', 'FALSE' ], true ); + + if ( $documentType === 'income' ) + return $isIncome; + + return !$isIncome; + } + + private function isDateRelevantForImport( $rawDocument ) + { + if ( isset( $rawDocument['invoice'] ) && is_array( $rawDocument['invoice'] ) ) + $rawDocument = $rawDocument['invoice']; + + if ( !is_array( $rawDocument ) ) + return false; + + $date = (string)( $rawDocument['issue_date'] ?? $rawDocument['sell_date'] ?? $rawDocument['created_at'] ?? '' ); + $date = substr( $date, 0, 10 ); + if ( !$date ) + return false; + + return strtotime( $date ) >= strtotime( $this -> startDate ); + } + + private function normalizeDocument( $rawDocument, $documentType ) + { + if ( isset( $rawDocument['invoice'] ) && is_array( $rawDocument['invoice'] ) ) + $rawDocument = $rawDocument['invoice']; + + if ( !is_array( $rawDocument ) ) + return null; + + $externalId = isset( $rawDocument['id'] ) ? (string)$rawDocument['id'] : ''; + if ( $externalId === '' ) + return null; + + $number = (string)( $rawDocument['number'] ?? $rawDocument['full_number'] ?? '' ); + $date = (string)( $rawDocument['issue_date'] ?? $rawDocument['sell_date'] ?? $rawDocument['created_at'] ?? date( 'Y-m-d' ) ); + $date = substr( $date, 0, 10 ); + + if ( $documentType === 'income' ) + { + $clientName = (string)( $rawDocument['buyer_name'] ?? $rawDocument['client_name'] ?? 'Nieznany klient' ); + $clientTaxNo = (string)( $rawDocument['buyer_tax_no'] ?? $rawDocument['tax_no'] ?? '' ); + } + else + { + $clientName = (string)( $rawDocument['seller_name'] ?? $rawDocument['client_name'] ?? 'Nieznany kontrahent' ); + $clientTaxNo = (string)( $rawDocument['seller_tax_no'] ?? $rawDocument['tax_no'] ?? '' ); + } + + $positions = []; + $totalAmount = 0.0; + + $rawPositions = $this -> resolvePositions( $rawDocument ); + foreach ( $rawPositions as $rawPosition ) + { + if ( !is_array( $rawPosition ) ) + continue; + + $name = trim( (string)( $rawPosition['name'] ?? '' ) ); + if ( $name === '' ) + $name = 'Pozycja'; + + $amount = $this -> resolvePositionAmount( $rawPosition ); + $totalAmount += $amount; + + $positions[] = [ + 'item_key' => $this -> buildItemKey( $rawPosition, $name ), + 'name' => $name, + 'amount' => $amount + ]; + } + + if ( empty( $positions ) ) + { + $fallback = (float)( $rawDocument['price_gross'] ?? $rawDocument['price'] ?? 0 ); + $fallbackName = trim( (string)( $rawDocument['product_cache'] ?? '' ) ); + if ( $fallbackName === '' ) + $fallbackName = 'Faktura bez pozycji'; + + if ( $fallback != 0.0 ) + { + $positions[] = [ + 'item_key' => $this -> buildItemKey( [], $fallbackName ), + 'name' => $fallbackName, + 'amount' => $fallback + ]; + $totalAmount = $fallback; + } + } + + if ( empty( $positions ) ) + return null; + + return [ + 'external_id' => $externalId, + 'document_key' => $documentType . ':' . $externalId, + 'number' => $number, + 'date' => $date, + 'client_name' => $clientName, + 'client_tax_no' => $clientTaxNo, + 'client_key' => $this -> buildClientKey( $rawDocument, $clientName, $clientTaxNo ), + 'positions' => $positions, + 'total_amount' => $this -> normalizeAmount( $totalAmount, $documentType ) + ]; + } + + private function resolvePositions( $rawDocument ) + { + if ( isset( $rawDocument['positions'] ) && is_array( $rawDocument['positions'] ) && !empty( $rawDocument['positions'] ) ) + return $rawDocument['positions']; + + $invoiceId = isset( $rawDocument['id'] ) ? (int)$rawDocument['id'] : 0; + if ( $invoiceId <= 0 ) + return []; + + $details = $this -> apiClient -> fetchInvoiceDetails( $invoiceId ); + if ( is_array( $details ) && isset( $details['positions'] ) && is_array( $details['positions'] ) ) + return $details['positions']; + + return []; + } + + private function resolvePositionAmount( $position ) + { + $quantity = (float)( $position['quantity'] ?? 1 ); + if ( $quantity <= 0 ) + $quantity = 1; + + $totalNet = (float)( $position['total_price_net'] ?? 0 ); + if ( $totalNet != 0.0 ) + return $totalNet; + + $unitNet = (float)( $position['price'] ?? $position['price_net'] ?? 0 ); + if ( $unitNet != 0.0 ) + return $unitNet * $quantity; + + // Fallback dla pozycji, ktore nie maja netto w payloadzie. + $totalGross = (float)( $position['total_price_gross'] ?? 0 ); + if ( $totalGross != 0.0 ) + return $totalGross; + + $unitGross = (float)( $position['price_gross'] ?? 0 ); + if ( $unitGross != 0.0 ) + return $unitGross * $quantity; + + return 0.0; + } + + private function buildClientKey( $rawDocument, $clientName, $clientTaxNo ) + { + if ( isset( $rawDocument['client_id'] ) && (string)$rawDocument['client_id'] !== '' ) + return 'id:' . (string)$rawDocument['client_id']; + + if ( $clientTaxNo !== '' ) + return 'tax:' . preg_replace( '/\s+/', '', $clientTaxNo ); + + return 'name:' . $this -> normalizeKeyValue( $clientName ); + } + + private function buildItemKey( $rawPosition, $name ) + { + if ( isset( $rawPosition['product_id'] ) && (string)$rawPosition['product_id'] !== '' ) + return 'product:' . (string)$rawPosition['product_id']; + + return 'name:' . $this -> normalizeKeyValue( $name ); + } + + private function normalizeKeyValue( $value ) + { + $value = trim( (string)$value ); + if ( function_exists( 'mb_strtolower' ) ) + return mb_strtolower( $value, 'UTF-8' ); + + return strtolower( $value ); + } + + private function normalizeAmount( $amount, $documentType ) + { + $amount = (float)$amount; + if ( $documentType === 'cost' ) + return abs( $amount ) * -1; + + return abs( $amount ); + } + + private function buildDescription( $document, $position ) + { + $parts = [ + 'Fakturownia' + ]; + + if ( $document['number'] !== '' ) + $parts[] = 'FV: ' . $document['number']; + + $parts[] = $position['name']; + $parts[] = $document['client_name']; + + return implode( ' | ', $parts ); + } + + private function resolveConfig() + { + $domain = trim( (string)\Env::get( 'FAKTUROWNIA_API_DOMAIN', '' ) ); + $token = trim( (string)\Env::get( 'FAKTUROWNIA_API_TOKEN', '' ) ); + $startDate = trim( (string)\Env::get( 'FAKTUROWNIA_START_DATE', '' ) ); + $pageLimit = (int)\Env::get( 'FAKTUROWNIA_PAGE_LIMIT', 100 ); + + if ( $domain === '' || $token === '' || $startDate === '' ) + return [ 'status' => 'error', 'ok' => false, 'msg' => 'Import Fakturownia: brak konfiguracji w .env.' ]; + + if ( !preg_match( '/^\d{4}-\d{2}-\d{2}$/', $startDate ) ) + return [ 'status' => 'error', 'ok' => false, 'msg' => 'Import Fakturownia: nieprawidlowa data FAKTUROWNIA_START_DATE.' ]; + + if ( strpos( $domain, 'http://' ) !== 0 && strpos( $domain, 'https://' ) !== 0 ) + $domain = 'https://' . $domain; + + return [ + 'ok' => true, + 'api_url' => rtrim( $domain, '/' ), + 'token' => $token, + 'start_date' => $startDate, + 'page_limit' => $pageLimit > 0 ? $pageLimit : 100 + ]; + } + + private function formatMessage( $summary ) + { + return 'Import Fakturownia: zaimportowano ' . (int)$summary['imported'] + . ', pominieto ' . (int)$summary['skipped'] + . ', brak mapowan ' . (int)$summary['unmapped'] + . ', bledy ' . (int)$summary['errors'] . '.'; + } +} diff --git a/autoload/Domain/Finances/FinanceRepository.php b/autoload/Domain/Finances/FinanceRepository.php index 7d7966e..3566bc5 100644 --- a/autoload/Domain/Finances/FinanceRepository.php +++ b/autoload/Domain/Finances/FinanceRepository.php @@ -55,6 +55,23 @@ class FinanceRepository return $this -> mdb -> select( 'crm_client', [ 'id', 'firm' ], [ 'ORDER' => [ 'firm' => 'ASC' ] ] ); } + public function categoriesFlatList() + { + return $this -> mdb -> select( 'finance_categories', [ 'id', 'name', 'group_id', 'parent_id' ], [ + 'ORDER' => [ 'name' => 'ASC' ] + ] ); + } + + public function clientExists( $clientId ) + { + return (bool)$this -> mdb -> has( 'crm_client', [ 'id' => (int)$clientId ] ); + } + + public function categoryExists( $categoryId ) + { + return (bool)$this -> mdb -> has( 'finance_categories', [ 'id' => (int)$categoryId ] ); + } + public function clientsWithRevenue( $date_from, $date_to, $group_id ) { return $this -> mdb -> query( diff --git a/autoload/class.Cron.php b/autoload/class.Cron.php index 4758384..2225c50 100644 --- a/autoload/class.Cron.php +++ b/autoload/class.Cron.php @@ -2,6 +2,22 @@ class Cron { + public static function import_finances_from_fakturownia() + { + try + { + $importer = new \Domain\Finances\FakturowniaInvoiceImporter(); + return $importer -> import(); + } + catch ( \Throwable $e ) + { + return [ + 'status' => 'error', + 'msg' => 'Import Fakturownia: ' . $e -> getMessage() + ]; + } + } + public static function recursive_tasks() { global $mdb; diff --git a/autoload/class.Env.php b/autoload/class.Env.php new file mode 100644 index 0000000..69737ee --- /dev/null +++ b/autoload/class.Env.php @@ -0,0 +1,64 @@ += 2 ) + { + $first = $value[0]; + $last = $value[strlen( $value ) - 1]; + if ( ( $first === '"' && $last === '"' ) || ( $first === "'" && $last === "'" ) ) + $value = substr( $value, 1, -1 ); + } + + self::$values[ $key ] = $value; + $_ENV[ $key ] = $value; + putenv( $key . '=' . $value ); + } + } + + public static function get( $key, $default = null ) + { + self::load(); + + $value = getenv( $key ); + if ( $value !== false ) + return $value; + + if ( isset( self::$values[ $key ] ) ) + return self::$values[ $key ]; + + return $default; + } +} diff --git a/cron.php b/cron.php index 9f09c5d..4d6a32d 100644 --- a/cron.php +++ b/cron.php @@ -1,4 +1,4 @@ - dispense( $type ); } ); +/* diagnostyka: wymuszenie pojedynczego joba cron */ +if ( \S::get( 'job' ) === 'fakturownia' ) +{ + $response = \Cron::import_finances_from_fakturownia(); + echo json_encode( $response ); + exit; +} + +/* import faktur z Fakturowni */ +$response = \Cron::import_finances_from_fakturownia(); +if ( $response['status'] == 'ok' ) +{ + echo json_encode( $response ); + exit; +} +if ( $response['status'] == 'error' ) +{ + echo json_encode( $response ); + exit; +} + /* import zadan z email */ $response = \Cron::import_tasks_from_email(); if ( $response['status'] == 'ok' ) @@ -66,10 +88,9 @@ if ( $response['status'] == 'error' ) exit; } - if ( date( 'G' ) > 6 ) { - /* wysyłanie przypomnnień do zadań */ + /* wysylanie przypomnien do zadan */ $response = \Cron::tasks_emails(); if ( $response['status'] == 'ok' ) { @@ -78,7 +99,7 @@ if ( date( 'G' ) > 6 ) } } -/* dodawanie zadań rekursywnych */ +/* dodawanie zadan rekursywnych */ $response = \Cron::recursive_tasks(); if ( $response['status'] == 'ok' ) { diff --git a/layout/style.css b/layout/style.css index 2244b99..52a4e9b 100644 --- a/layout/style.css +++ b/layout/style.css @@ -1 +1 @@ -.default-btn,.task_popup .task_details .content .right .time a:not(.time_worked_toggle),.task_popup .task_details .content .right .time a.time_worked_toggle{display:flex;align-items:center;justify-content:center;height:40px;border-radius:6px;padding:0 15px;transition:all .3s ease}.default-btn:hover,.task_popup .task_details .content .right .time a:hover:not(.time_worked_toggle),.task_popup .task_details .content .right .time a.time_worked_toggle:hover{text-decoration:none}.animate{animation:mymove 3s infinite}.text-right{text-align:right}.nowrap{white-space:nowrap}table{border-collapse:collapse;font-size:13px}small{font-size:.75em}@keyframes mymove{50%{opacity:.33}}@keyframes gradient-animation{0%{background-position:15% 0%}50%{background-position:85% 100%}100%{background-position:15% 0%}}@keyframes frame-enter{0%{clip-path:polygon(0% 100%, 3px 100%, 3px 3px, calc(100% - 3px) 3px, calc(100% - 3px) calc(100% - 3px), 3px calc(100% - 3px), 3px 100%, 100% 100%, 100% 0%, 0% 0%)}25%{clip-path:polygon(0% 100%, 3px 100%, 3px 3px, calc(100% - 3px) 3px, calc(100% - 3px) calc(100% - 3px), calc(100% - 3px) calc(100% - 3px), calc(100% - 3px) 100%, 100% 100%, 100% 0%, 0% 0%)}50%{clip-path:polygon(0% 100%, 3px 100%, 3px 3px, calc(100% - 3px) 3px, calc(100% - 3px) 3px, calc(100% - 3px) 3px, calc(100% - 3px) 3px, calc(100% - 3px) 3px, 100% 0%, 0% 0%)}75%{-webkit-clip-path:polygon(0% 100%, 3px 100%, 3px 3px, 3px 3px, 3px 3px, 3px 3px, 3px 3px, 3px 3px, 3px 0%, 0% 0%)}100%{-webkit-clip-path:polygon(0% 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 0% 100%)}}*{box-sizing:border-box}body{font-family:"Open Sans",sans-serif;margin:0;padding:0;font-size:15px;color:#4e5e6a}.btn{padding:9px 25px;transition:all .3s ease;color:#fff;border:0;border-radius:6px;cursor:pointer;display:inline-flex;text-decoration:none;gap:5px;justify-content:center;align-items:center}.btn.btn_small,.btn.btn-xs,.btn.btn-sm{padding:5px 7px;font-size:13px}.btn.btn_small i,.btn.btn-xs i,.btn.btn-sm i{font-size:12px}.btn.btn-success{background:#099885}.btn.btn-success:hover{background:#4a9c3b}.btn.btn-primary{background:#6690f4}.btn.btn-primary:hover{background:#3164db}.btn.btn-danger{background:#cc563d}.btn.btn-danger:hover{background:#b30000}.hide{display:none}.form-error{color:#cc563d;font-size:13px}.input-group{margin-bottom:10px}.form-field{margin-bottom:15px}.form-field label{display:block;font-size:13px;font-weight:600;margin-bottom:4px;color:#4e5e6a}.password-wrap{position:relative}.password-wrap .form-control{padding-right:40px}.password-wrap .password-eye{position:absolute;right:10px;top:50%;transform:translateY(-50%);color:#999;text-decoration:none;z-index:2}.password-wrap .password-eye:hover{color:#333}input[type=checkbox]{border:1px solid #cdcdcd}.form-control{border:1px solid #cdcdcd;border-radius:6px;height:35px;width:100%;padding:5px;font-family:"Open Sans",sans-serif}.form-control option{padding:5px}.form-control:focus{border:1px solid #6690f4;outline:none}.unlogged{background:#eef1f9;display:flex;align-items:center;justify-content:center;height:100vh}.unlogged .box-login{background:#fff;padding:25px;border-radius:6px;width:400px}.unlogged .box-login .title{text-align:center;padding:10px 10px 25px;border-bottom:1px solid #cdcdcd;font-size:20px;margin-bottom:25px}.sidebar{position:fixed;top:0;left:0;width:220px;height:100vh;background:#1e2a3a;display:flex;flex-direction:column;z-index:1000;transition:width .3s ease;overflow:hidden}.sidebar.collapsed{width:60px}.sidebar.collapsed .sidebar-header .sidebar-logo span,.sidebar.collapsed .sidebar-nav ul li a span,.sidebar.collapsed .sidebar-footer span,.sidebar.collapsed .sidebar-footer .sidebar-user span{display:none}.sidebar.collapsed .sidebar-header .sidebar-logo{font-size:0}.sidebar.collapsed .sidebar-header .sidebar-logo::first-letter{font-size:16px}.sidebar.collapsed .sidebar-nav ul li a{justify-content:center;padding:10px}.sidebar.collapsed .sidebar-nav ul li a i{margin-right:0}.sidebar.collapsed .sidebar-nav ul li.has-submenu .submenu-arrow{display:none}.sidebar.collapsed .sidebar-nav ul li.has-submenu .sidebar-submenu{display:none}.sidebar.collapsed .sidebar-footer .sidebar-footer-link,.sidebar.collapsed .sidebar-footer .sidebar-user{justify-content:center;padding:8px 10px}.sidebar.collapsed .sidebar-footer .sidebar-footer-link i,.sidebar.collapsed .sidebar-footer .sidebar-user i{margin-right:0}.sidebar .sidebar-header{display:flex;align-items:center;justify-content:space-between;padding:15px;border-bottom:1px solid hsla(0,0%,100%,.1)}.sidebar .sidebar-header .sidebar-logo{color:#6690f4;text-decoration:none;font-size:16px;white-space:nowrap}.sidebar .sidebar-header .sidebar-logo span{font-weight:700}.sidebar .sidebar-header .sidebar-toggle{cursor:pointer;color:#c2c7d0;font-size:16px;transition:color .2s ease}.sidebar .sidebar-header .sidebar-toggle:hover{color:#fff}.sidebar .sidebar-nav{flex:1;overflow-y:auto;padding:10px 0}.sidebar .sidebar-nav ul{list-style:none;margin:0;padding:0}.sidebar .sidebar-nav ul li a{display:flex;align-items:center;padding:10px 15px;color:#c2c7d0;text-decoration:none;font-size:14px;transition:all .2s ease;white-space:nowrap}.sidebar .sidebar-nav ul li a i{width:20px;text-align:center;margin-right:10px;font-size:15px}.sidebar .sidebar-nav ul li a:hover{background:hsla(0,0%,100%,.08);color:#fff}.sidebar .sidebar-nav ul li.active a{background:hsla(0,0%,100%,.08);color:#fff;font-weight:600}.sidebar .sidebar-nav ul li.has-submenu>a .submenu-arrow{margin-left:auto;font-size:12px;transition:transform .2s ease;width:auto}.sidebar .sidebar-nav ul li.has-submenu.open>a .submenu-arrow{transform:rotate(180deg)}.sidebar .sidebar-nav ul li.has-submenu .sidebar-submenu{max-height:0;overflow:hidden;transition:max-height .25s ease;background:rgba(0,0,0,.15)}.sidebar .sidebar-nav ul li.has-submenu .sidebar-submenu li a{padding:8px 15px 8px 45px;font-size:13px}.sidebar .sidebar-nav ul li.has-submenu .sidebar-submenu li a i{font-size:13px;width:16px}.sidebar .sidebar-nav ul li.has-submenu.open .sidebar-submenu{max-height:200px}.sidebar .sidebar-footer{border-top:1px solid hsla(0,0%,100%,.1);padding:10px 0}.sidebar .sidebar-footer .sidebar-user{display:flex;align-items:center;padding:8px 15px;color:#c2c7d0;font-size:13px;white-space:nowrap;overflow:hidden}.sidebar .sidebar-footer .sidebar-user i{margin-right:10px;color:#6690f4}.sidebar .sidebar-footer .sidebar-footer-link{display:flex;align-items:center;padding:8px 15px;color:#c2c7d0;text-decoration:none;font-size:13px;transition:all .2s ease;white-space:nowrap}.sidebar .sidebar-footer .sidebar-footer-link i{width:20px;text-align:center;margin-right:10px}.sidebar .sidebar-footer .sidebar-footer-link:hover{background:hsla(0,0%,100%,.08);color:#fff}.sidebar .sidebar-footer .sidebar-footer-link.logout{color:#cc563d}.sidebar .sidebar-footer .sidebar-footer-link.logout:hover{color:#e07a66}.content-wrapper{margin-left:220px;min-height:100vh;transition:margin-left .3s ease}.content-wrapper.expanded{margin-left:60px}.top-bar{background:#fff;border-bottom:1px solid #e8e8e8;padding:10px 20px;display:flex;align-items:center}.top-bar .top-bar-left{display:flex;align-items:center;gap:15px}.top-bar .top-bar-left i{cursor:pointer;font-size:18px;color:#4e5e6a}.top-bar .top-bar-left i:hover{color:#000}.main{padding:25px;background:#d9dee2;min-height:calc(100vh - 45px)}.tasks_container{display:grid;grid-template-columns:repeat(5, 1fr);gap:20px}.tasks_container .column{width:100%}.tasks_container .column h2{display:flex;padding:10px;background:#fff;margin-bottom:10px;font-size:15px;font-weight:300;border-radius:3px 3px 0 0;justify-content:space-between;align-items:center}.tasks_container .column h2 i{cursor:pointer}.tasks_container .column.tasks_suspended h2{border-bottom:5px solid #cc563d}.tasks_container .column.tasks_fvat h2{border-bottom:5px solid #a900fc}.tasks_container .column.tasks_new h2{border-bottom:5px solid #ccc}.tasks_container .column.tasks_bulk h2{border-bottom:5px solid #ff8c00}.tasks_container .column.tasks_to_do h2{border-bottom:5px solid #2aaf47}.tasks_container .column.tasks_to_review h2{border-bottom:5px solid #2535c9}.tasks_container .column.tasks_closed h2{border-bottom:5px solid #000}.tasks_container .column ul{list-style-type:none;margin:0;padding:0}.tasks_container .column ul .task{margin-bottom:5px;background:#fff;padding:10px;border-radius:0;display:flex;position:relative;border-radius:6px;flex-wrap:wrap}.tasks_container .column ul .task.notopened{border:2px solid #cc563d}.tasks_container .column ul .task .top{display:flex;justify-content:space-between;margin-bottom:5px;width:100%}.tasks_container .column ul .task .top ._users{display:flex;gap:5px;flex-wrap:wrap}.tasks_container .column ul .task .top ._users .user{display:flex;width:25px;height:25px;border-radius:6px;justify-content:center;align-items:center;color:#fff;font-size:12px}.tasks_container .column ul .task .top ._timer{display:flex;gap:5px}.tasks_container .column ul .task .top ._timer .recursively{color:#fff;background:#405189;border-radius:3px;cursor:pointer;margin-bottom:5px;width:25px;height:25px;text-align:center;display:block}.tasks_container .column ul .task .top ._timer .recursively i{font-size:12px}.tasks_container .column ul .task .top ._timer .task_start{display:block;background:#099885;color:#fff;border-radius:6px;cursor:pointer;margin-bottom:5px;width:25px;height:25px;text-align:center}.tasks_container .column ul .task .top ._timer .task_start.hidden{display:none}.tasks_container .column ul .task .top ._timer .task_start i{font-size:12px}.tasks_container .column ul .task .top ._timer .task_end{background:#cc563d;display:block;color:#fff;border-radius:6px;cursor:pointer;margin-bottom:5px;width:25px;height:25px;text-align:center}.tasks_container .column ul .task .top ._timer .task_end.hidden{display:none}.tasks_container .column ul .task .top ._timer .task_end i{font-size:12px}.tasks_container .column ul .task .middle{width:100%}.tasks_container .column ul .task .name{font-size:14px;color:#333;text-decoration:none;display:block;margin-bottom:5px}.tasks_container .column ul .task .bottom{display:flex;justify-content:space-between}.tasks_container .column ul .task .client_info,.tasks_container .column ul .task .current_status{font-size:12px;font-weight:400}.tasks_container .column ul .task .client_info strong,.tasks_container .column ul .task .current_status strong{font-weight:600}.tasks_container .column ul .task .current_status{position:relative;cursor:pointer}.tasks_container .column ul .task .current_status .status_change{position:absolute;left:0;top:20px;background:#fff;padding:15px;border:1px solid #dfdfdf;border-radius:3px;cursor:pointer;box-shadow:0 0 15px rgba(0,0,0,.1);z-index:99;display:none}.tasks_container .column ul .task .current_status .status_change select{width:250px;padding:10px;border:1px solid #cdcdcd;border-radius:3px}.tasks_container .column ul .task .current_status .status_change select option{font-size:15px;padding:3px}.tasks_container .column ul .task .dates{margin-bottom:5px;display:flex;justify-content:space-between;font-size:12px}.tasks_container .column ul .task .dates .danger{color:#cc563d;font-weight:600}.tasks_container .column ul .task .dates .warning{color:#ff8c00}.tasks_container .column ul .task .dates i{font-size:12px;color:#c9ced4;margin-right:5px}.block-header{margin-bottom:20px}.block-header h2{font-size:20px;font-weight:400;color:#4e5e6a;margin:0;padding-bottom:12px;border-bottom:2px solid #e2e6ec}.block-header h2 strong{font-weight:700}.filters-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:24px;padding:12px 16px;background:#f5f7fa;border-radius:8px;border:1px solid #e2e6ec}.filters-bar select,.filters-bar input[type=text],.filters-bar input[type=date],.filters-bar input[type=number]{height:36px;min-width:170px;padding:0 10px;border:1px solid #d0d5dd;border-radius:6px;background:#fff;font-size:13px;color:#4e5e6a;font-family:"Open Sans",sans-serif;transition:border-color .2s}.filters-bar select:focus,.filters-bar input[type=text]:focus,.filters-bar input[type=date]:focus,.filters-bar input[type=number]:focus{border-color:#6690f4;outline:none}.filters-bar .btn{height:36px;display:inline-flex;align-items:center;gap:5px;padding:0 14px;border-radius:6px;font-size:13px;font-weight:500;border:none;cursor:pointer;transition:background .2s,box-shadow .2s;text-decoration:none;color:#fff}.filters-bar .btn.btn-primary{background:#6690f4}.filters-bar .btn.btn-primary:hover{background:#4a74d4}.filters-bar .btn.btn-success{background:#099885}.filters-bar .btn.btn-success:hover{background:#077a6b}.section-title{font-size:14px;font-weight:600;color:#4e5e6a;margin:28px 0 12px;padding-bottom:8px;border-bottom:1px solid #e2e6ec}.action_menu{display:flex;margin-bottom:25px;gap:20px}.action_menu .btn{display:inline-flex;padding:7px 15px;color:#fff;text-decoration:none;align-items:center;justify-content:center;gap:5px}.action_menu .btn.btn_add{background:#099885}.action_menu .btn.btn_add:hover{background:#4a9c3b}.action_menu .btn.btn_cancel{background:#cc563d}.action_menu .btn.btn_cancel:hover{background:#b30000}.action_menu .btn.disabled{opacity:.5}.form_container{background:#fff;padding:25px;max-width:1300px}.form_container.full{max-width:100%}.form_container .form_group{margin-bottom:10px;display:flex}.form_container .form_group>.label{width:300px;display:inline-flex;align-items:flex-start;justify-content:right;padding-right:10px}.form_container .form_group .input{width:calc(100% - 300px)}.fullscreen_description{position:fixed !important;top:25px;left:25px;right:25px;bottom:25px;z-index:9999;background:#fff;padding:20px;overflow:auto;border-radius:.25rem;box-shadow:0 0 20px rgba(0,0,0,.3)}.fullscreen{position:absolute;top:10px;right:10px;cursor:pointer;color:#fff;background:#cc563d;display:inline-flex;height:40px;width:40px;border-radius:6px;align-items:center;justify-content:center;transition:all .3s ease}.fullscreen:hover{transform:scale(1.05);text-decoration:none}.task_popup{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.5);display:none;z-index:9999}.task_popup .task_details{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);background:#fff;padding:25px;border-radius:6px;max-width:1140px;width:100%;transition:all .3s ease;height:90vh}.task_popup .task_details .content{height:calc(100% - 50px)}.task_popup .task_details.open_works_time{max-width:1540px}.task_popup .task_details.open_works_time .content{grid-template-columns:1fr 300px 350px}.task_popup .task_details.open_works_time .content .task_work_details{display:block}.task_popup .task_details .title{font-size:20px;margin-bottom:25px;display:flex;align-items:center;gap:10px}.task_popup .task_details .title a{border:1px solid #099885;display:inline-flex;height:30px;width:30px;border-radius:6px;align-items:center;justify-content:center}.task_popup .task_details .title a:hover{text-decoration:none}.task_popup .task_details .title a i{color:#099885}.task_popup .task_details .title a.task-delete{border:1px solid #cc563d}.task_popup .task_details .title a.task-delete i{color:#cc563d}.task_popup .task_details .title a i{font-size:14px}.task_popup .task_details .title .task-title-edit-box{align-items:center;gap:6px}.task_popup .task_details .title .task-title-edit-box .task-title-input{height:30px;font-size:14px;padding:2px 8px;width:300px;border:1px solid #ccc;border-radius:4px}.task_popup .task_details .title .task-title-edit-box a.task-title-save,.task_popup .task_details .title .task-title-edit-box a.task-title-cancel{height:30px;width:30px;display:inline-flex;align-items:center;justify-content:center;border-radius:6px}.task_popup .task_details .title .task-title-edit-box a.task-title-save i,.task_popup .task_details .title .task-title-edit-box a.task-title-cancel i{font-size:13px}.task_popup .task_details .title .task-title-edit-box a.task-title-save{background:#099885;border-color:#099885}.task_popup .task_details .title .task-title-edit-box a.task-title-save i{color:#fff}.task_popup .task_details .title .task-title-edit-box a.task-title-cancel{background:#cc563d;border-color:#cc563d}.task_popup .task_details .title .task-title-edit-box a.task-title-cancel i{color:#fff}.task_popup .task_details .close{position:absolute;top:10px;right:10px;cursor:pointer}.task_popup .task_details .content{display:grid;font-size:14px;grid-template-columns:1fr 300px;gap:30px;transition:all .3s ease}.task_popup .task_details .content h3{width:100%;margin-top:0;margin-bottom:5px;font-weight:500;color:#000;font-size:17px}.task_popup .task_details .content .left{height:100%;overflow:hidden}.task_popup .task_details .content .left .users{display:flex;gap:20px}.task_popup .task_details .content .left .users .user{display:flex;gap:10px;align-items:center;margin-bottom:10px}.task_popup .task_details .content .left .users .user .avatar{height:30px;width:30px;border-radius:6px;background:#ccc;display:flex;justify-content:center;align-items:center;color:#fff;font-size:12px}.task_popup .task_details .content .left .comments{border-radius:3px;max-height:406px;overflow-y:auto}.task_popup .task_details .content .left .comments .new_comment{margin-bottom:10px}.task_popup .task_details .content .left .comments .new_comment textarea{height:75px;margin-bottom:10px;border-radius:6px}.task_popup .task_details .content .left .comments .new_comment .add_comment{background:#099885;color:#fff;padding:10px;border-radius:6px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;width:200px;text-decoration:none}.task_popup .task_details .content .left .comments .new_comment .add_comment:hover{background:#4a9c3b}.task_popup .task_details .content .left .comments ul{margin:0;padding:0;list-style-type:none}.task_popup .task_details .content .left .comments ul li{background:#ced4da;margin-bottom:5px;padding:15px;border-radius:6px;position:relative}.task_popup .task_details .content .left .comments ul li .delete_comment{position:absolute;top:10px;right:10px;cursor:pointer;color:#cc563d}.task_popup .task_details .content .left .comments ul li .author{font-weight:600;margin-bottom:5px;display:inline-flex;margin-right:10px}.task_popup .task_details .content .left .comments ul li .date{font-size:12px;margin-bottom:5px;display:inline-flex}.task_popup .task_details .content .left .comments ul li .text{margin-bottom:15px;font-size:13px}.task_popup .task_details .content .left .checklist{border-radius:3px;margin-bottom:10px}.task_popup .task_details .content .left .checklist .new_element{display:flex;margin-bottom:10px}.task_popup .task_details .content .left .checklist .new_element input{border-radius:6px 0 0 6px}.task_popup .task_details .content .left .checklist .new_element a{display:flex;align-items:center;justify-content:center;padding:10px;border-radius:0 6px 6px 0;text-decoration:none;width:35px;background:#099885;color:#fff}.task_popup .task_details .content .left .checklist ul{margin:0;padding:0;list-style-type:none;overflow-y:auto;max-height:calc(90vh - 400px)}.task_popup .task_details .content .left .checklist ul li{display:flex;gap:10px;margin-bottom:5px;background:#fff;border-radius:3px;padding:10px;border:1px solid #cdcdcd;font-size:13px;align-items:flex-start}.task_popup .task_details .content .left .checklist ul li a{margin-left:auto;margin-right:0;cursor:pointer;background:#cc563d;display:flex;height:25px;width:25px;min-width:25px;justify-content:center;align-items:center;border:0;border-radius:3px;transition:all .3s ease}.task_popup .task_details .content .left .checklist ul li a:hover{text-decoration:none;background:#b30000}.task_popup .task_details .content .left .checklist ul li a i{color:#fff;font-size:12px}.task_popup .task_details .content .left .attachments{margin-top:10px;border:1px solid #e6e9ed;border-radius:8px;padding:12px;background:#f9fbfd}.task_popup .task_details .content .left .attachments h3{margin-bottom:10px;font-size:16px;font-weight:600}.task_popup .task_details .content .left .attachments .attachments_upload{display:flex;gap:10px;align-items:center;margin-bottom:10px}.task_popup .task_details .content .left .attachments .attachments_upload .attachment_file_input{flex:1;margin-bottom:0;border-radius:6px;background:#fff}.task_popup .task_details .content .left .attachments .attachments_upload .attachment-upload-btn{white-space:nowrap;border-radius:6px;min-width:150px}.task_popup .task_details .content .left .attachments .attachments_upload .attachment-upload-btn.is-loading{pointer-events:none;opacity:.85}.task_popup .task_details .content .left .attachments .attachments_upload .attachment-upload-btn.is-loading i{margin-right:6px}.task_popup .task_details .content .left .attachments .attachments_list{margin:0;padding:0;list-style:none;display:grid;gap:8px;max-height:180px;overflow-y:auto}.task_popup .task_details .content .left .attachments .attachments_list li{display:flex;align-items:center;gap:8px;background:#fff;border:1px solid #e4e8ee;border-radius:6px;padding:8px 10px}.task_popup .task_details .content .left .attachments .attachments_list li .attachment-link{color:#1f3d72;text-decoration:none;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:calc(100% - 140px)}.task_popup .task_details .content .left .attachments .attachments_list li .attachment-link:hover{text-decoration:underline}.task_popup .task_details .content .left .attachments .attachments_list li small{color:#6b7280;margin-right:auto}.task_popup .task_details .content .left .attachments .attachments_list li .attachment-rename,.task_popup .task_details .content .left .attachments .attachments_list li .attachment-delete{display:inline-flex;align-items:center;justify-content:center;height:28px;width:28px;border-radius:4px;text-decoration:none;transition:all .2s ease}.task_popup .task_details .content .left .attachments .attachments_list li .attachment-rename{border:1px solid #d8e2f6;color:#6690f4;background:#f4f8ff}.task_popup .task_details .content .left .attachments .attachments_list li .attachment-rename:hover{background:#e7f0ff}.task_popup .task_details .content .left .attachments .attachments_list li .attachment-delete{border:1px solid #f1d3d1;color:#cc563d;background:#fff6f6}.task_popup .task_details .content .left .attachments .attachments_list li .attachment-delete:hover{background:#ffeaea}.task_popup .task_details .content .left .attachments .attachments_list .attachments-empty{color:#6b7280;border-style:dashed;justify-content:center;font-size:13px}.task_popup .task_details .content .left .description{padding:15px;border-radius:.25rem;border:1px solid #cdcdcd;margin-bottom:15px;max-height:202px;overflow-x:hidden;position:relative}.task_popup .task_details .content .right .box{margin-bottom:15px}.task_popup .task_details .content .right .time a.time_worked_toggle{color:#299cdb;display:inline-flex;border:1px solid #299cdb}.task_popup .task_details .content .right .time a.time_worked_toggle:hover{background:#dff0fa;text-decoration:none}.task_popup .task_details .content .right .time a.time_worked_toggle:active,.task_popup .task_details .content .right .time a.time_worked_toggle:focus{text-decoration:none}.task_popup .task_details .content .right .time a:not(.time_worked_toggle){margin-top:10px;text-decoration:none;gap:10px}.task_popup .task_details .content .right .time a:not(.time_worked_toggle).task_start{background:#0ab39c;color:#fff}.task_popup .task_details .content .right .time a:not(.time_worked_toggle).task_start:hover{background:#099885}.task_popup .task_details .content .right .time a:not(.time_worked_toggle).task_end{background:#cc563d;color:#fff}.task_popup .task_details .content .right .time a:not(.time_worked_toggle).hidden{display:none}.task_popup .task_details .content .right .dates{display:flex;justify-content:space-between;flex-wrap:wrap}.task_popup .task_details .content .right .dates .danger{color:#cc563d;font-weight:600}.task_popup .task_details .content .right .dates .warning{color:#ff8c00}.task_popup .task_details .content .right .dates i{color:#c9ced4;margin-right:5px}.task_popup .task_details .content .task_work_details{display:none;overflow-y:auto;max-height:508px;width:100%;padding-right:10px;padding-top:4px}.task_popup .task_details .content .task_work_details ._line{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;margin-bottom:5px}.task_popup .task_details .content .task_work_details ._line ._user{width:100%;font-size:13px}.task_popup .task_details .content .task_work_details ._line input{width:calc(50% - 25px);text-align:center;margin-left:2px;margin-right:2px}.task_popup .task_details .content .task_work_details ._work_delete{display:inline-flex;height:35px;width:35px;border-radius:6px;align-items:center;justify-content:center;cursor:pointer;border:1px solid #cc563d;margin-left:2px;transition:all .3s ease}.task_popup .task_details .content .task_work_details ._work_delete:hover{background:#cc563d}.task_popup .task_details .content .task_work_details ._work_delete:hover i{color:#fff}.task_popup .task_details .content .task_work_details ._work_delete i{transition:all .3s ease;color:#cc563d}.table{width:100%;border:none;border-radius:8px;overflow:hidden;box-shadow:0 1px 3px rgba(0,0,0,.06);background:#fff}.table th,.table td{padding:10px 14px;border:none;border-bottom:1px solid #eef0f3;text-align:left;vertical-align:middle}.table thead th{background:#f5f7fa;color:#4e5e6a;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.3px;white-space:nowrap;border-bottom:2px solid #e2e6ec}.table tbody tr{transition:background .15s ease}.table tbody tr:last-child td{border-bottom:none}.table tbody tr:hover{background:#f8fafd}.table td.center,.table th.center{text-align:center}.table td.left,.table th.left{text-align:left}.table td.right,.table th.right{text-align:right}.table td[colspan]{text-align:center;color:#8896a4;padding:24px 14px;font-style:italic}.projects_container{background:#fff;padding:15px;border-radius:6px;display:flex;gap:20px}.projects_container .left{width:calc(100% - 250px)}.projects_container .left ._projects,.projects_container .left ._users{display:flex;gap:20px;flex-wrap:wrap}.projects_container .right{width:250px;display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:center;gap:20px;border-left:1px solid #cdcdcd;padding-left:15px}.projects_container .right select{width:200px}.default_popup{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.5);display:none}.default_popup .popup_content{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);background:#fff;padding:25px;border-radius:0;max-width:1140px;width:100%}.default_popup .popup_content .close{position:absolute;top:10px;right:10px;cursor:pointer}#fg-cron{margin:10px 0}#fg-cron .countdown{background:#099885;color:#fff;padding:10px}#fg-cron #cron-container{max-height:300px;overflow-x:hidden;overflow-y:auto}#fg-cron #cron-container .msg{font-size:13px;padding:5px;border-bottom:1px solid #e8e8e8}.card{background:#fff;padding:25px;border-radius:6px;color:#000;font-size:15px;max-width:1280px}.card.mb25{margin-bottom:25px}.card .card-header{font-weight:600}.card .card-body{padding-top:10px}.card .card-body table{border-collapse:collapse}.card .card-body table th,.card .card-body table td{font-size:14px}.card .card-body table th.bold,.card .card-body table td.bold{font-weight:600}.card .card-body table th.text-right,.card .card-body table td.text-right{text-align:right}.card .card-body table th.text-center,.card .card-body table td.text-center{text-align:center}.card .card-body table th .close-task,.card .card-body table td .close-task{text-decoration:none;color:#6690f4}.card .card-body table th .close-task:hover,.card .card-body table td .close-task:hover{color:#cc563d}.finance-summary{display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:10px}.finance-summary .panel{background:#fff;border-radius:6px;padding:15px}.finance-summary .panel h1{font-size:20px;margin:0}.finance-summary .panel span{font-size:.85em}.finance-manager{display:grid;gap:10px;grid-template-columns:200px 1fr 500px;padding-top:25px}.finance-manager .manage-menu{display:inline-block;margin-right:10px}.finance-manager .manage-menu a{color:#333;text-decoration:none;font-weight:300;display:block}.finance-manager .actions{width:100px;text-align:center}.finance-manager .actions a{display:inline-flex;margin:0 2px;height:25px;width:25px;align-items:center;justify-content:center;text-decoration:none;color:#000;border:1px solid #e7e7e7;font-size:11px;border-radius:3px;transition:all .3s ease}.finance-manager .actions a:hover{border:1px solid #6690f4}.bootstrap-tagsinput .tag{background:#6690f4;font-size:13px;padding:5px 10px;border-radius:12px}.bootstrap-tagsinput .tag [data-role=remove]{color:#fff !important}.bootstrap-tagsinput .tag [data-role=remove]:hover{box-shadow:none !important;color:#000 !important}.finance-tags{display:flex;flex-wrap:wrap;gap:5px}.finance-tags a:not(.btn){display:flex;width:100%;text-decoration:none;color:#4e5e6a}.finance-tags a:not(.btn).zoom-100{font-size:1.2em}.finance-tags a:not(.btn).zoom-90{font-size:1.15em}.finance-tags a:not(.btn).zoom-80{font-size:1.1em}.finance-tags a:not(.btn).zoom-70{font-size:1.05em}.finance-tags a:not(.btn).zoom-60{font-size:1em}.finance-tags a:not(.btn).zoom-50{font-size:.95em}.finance-tags a:not(.btn).zoom-40{font-size:.9em}.finance-tags a:not(.btn).zoom-30{font-size:.85em}.finance-tags a:not(.btn).zoom-20{font-size:.8em}.finance-tags a:not(.btn).zoom-10{font-size:.75em}.finance-tags a:not(.btn).zoom-0{font-size:.7em}.manage-menu{position:relative}.manage-menu .context-menu{border-left:4px dotted #000;width:1px;height:100%}.manage-menu .context-menu-container{position:absolute;display:none;background:#fff;box-shadow:5px 5px 15px rgba(0,0,0,.1);top:2px;left:2px}.manage-menu .context-menu-container ul{list-style-type:none;margin:0;padding:0}.manage-menu .context-menu-container ul li a{display:block;padding:7px 15px;white-space:nowrap}.manage-menu .context-menu-container ul li a:hover{background:#f8f8f8}.manage-menu:hover .context-menu-container{display:block}.wiki-categories{display:grid;gap:10px;margin-top:25px;grid-template-columns:1fr 1fr 1fr 1fr}.wiki-categories .category{background:#fff;padding:10px}.wiki-categories .category .users{display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:5px}.wiki-categories .category .users .user{display:flex;height:25px;width:25px;border-radius:50%;background:#ccc;justify-content:center;align-items:center;color:#fff;font-size:12px}.wiki-categories .category .actions{display:grid;grid-template-columns:1fr 1fr}.wiki-categories .category .actions a{display:block;color:#4e5e6a;font-size:13px;text-align:center}.wiki-categories .category .title{margin-bottom:5px}.wiki-categories .category .title a{display:block;color:#4e5e6a;font-size:13px;font-weight:600}.bootstrap-datetimepicker-widget .picker-switch a{display:block;color:#000}.gantt_users{display:flex;gap:20px}#g-results{background:#fff;padding:25px}.g-menu-container{margin-bottom:15px}.g-menu-container .right-menu{display:none}.g-center{text-align:center}.alert{background:#099885;border:0;color:#fff}.tasks_main_view{display:flex;gap:20px}.tasks_main_view ._left_column{padding:25px;background:#fcfcfc;border-right:1px solid #e8e8e8;width:350px}.tasks_main_view ._left_column label{font-weight:400;font-size:14px}.tasks_main_view ._left_column select[name=filtr]{margin-bottom:10px}.tasks_main_view ._left_column ._buttons{display:flex;gap:10px;justify-content:space-between}.tasks_main_view ._left_column ._buttons .btn{flex:1}.tasks_main_view ._right_column{flex:1;max-width:calc(100% - 350px)}#billing-summary .card-header{padding:10px}#billing-summary .billing-kpi{border:1px solid #dee2e6;border-radius:6px;padding:10px 12px;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.04)}#billing-summary .billing-kpi-label{font-size:12px;color:#6c757d;margin-bottom:3px}#billing-summary .billing-kpi-value{font-size:21px;font-weight:700;line-height:1.1}#billing-summary .billing-details-row{display:none}#billing-summary .billing-client-name{font-weight:600}#billing-summary .billing-table>thead>tr>th{background:#f8f9fa}#billing-summary .billing-details-wrap{background:#f8fbff}.vacation-type-badge{display:inline-block;padding:2px 8px;border-radius:4px;font-size:12px;font-weight:500;background:#e3f0ff;color:#2563eb}.vacation-type-badge.type-chorobowe{background:#fff3e0;color:#e65100}.vacation-type-badge.type-inna_nieobecnosc{background:#f3e5f5;color:#7b1fa2}/*# sourceMappingURL=style.css.map */ \ No newline at end of file +.default-btn,.task_popup .task_details .content .right .time a:not(.time_worked_toggle),.task_popup .task_details .content .right .time a.time_worked_toggle{display:flex;align-items:center;justify-content:center;height:40px;border-radius:6px;padding:0 15px;transition:all .3s ease}.default-btn:hover,.task_popup .task_details .content .right .time a:hover:not(.time_worked_toggle),.task_popup .task_details .content .right .time a.time_worked_toggle:hover{text-decoration:none}.animate{animation:mymove 3s infinite}.text-right{text-align:right}.nowrap{white-space:nowrap}table{border-collapse:collapse;font-size:13px}small{font-size:.75em}@keyframes mymove{50%{opacity:.33}}@keyframes gradient-animation{0%{background-position:15% 0%}50%{background-position:85% 100%}100%{background-position:15% 0%}}@keyframes frame-enter{0%{clip-path:polygon(0% 100%, 3px 100%, 3px 3px, calc(100% - 3px) 3px, calc(100% - 3px) calc(100% - 3px), 3px calc(100% - 3px), 3px 100%, 100% 100%, 100% 0%, 0% 0%)}25%{clip-path:polygon(0% 100%, 3px 100%, 3px 3px, calc(100% - 3px) 3px, calc(100% - 3px) calc(100% - 3px), calc(100% - 3px) calc(100% - 3px), calc(100% - 3px) 100%, 100% 100%, 100% 0%, 0% 0%)}50%{clip-path:polygon(0% 100%, 3px 100%, 3px 3px, calc(100% - 3px) 3px, calc(100% - 3px) 3px, calc(100% - 3px) 3px, calc(100% - 3px) 3px, calc(100% - 3px) 3px, 100% 0%, 0% 0%)}75%{-webkit-clip-path:polygon(0% 100%, 3px 100%, 3px 3px, 3px 3px, 3px 3px, 3px 3px, 3px 3px, 3px 3px, 3px 0%, 0% 0%)}100%{-webkit-clip-path:polygon(0% 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 0% 100%)}}*{box-sizing:border-box}body{font-family:"Open Sans",sans-serif;margin:0;padding:0;font-size:15px;color:#4e5e6a}.btn{padding:9px 25px;transition:all .3s ease;color:#fff;border:0;border-radius:6px;cursor:pointer;display:inline-flex;text-decoration:none;gap:5px;justify-content:center;align-items:center}.btn.btn_small,.btn.btn-xs,.btn.btn-sm{padding:5px 7px;font-size:13px}.btn.btn_small i,.btn.btn-xs i,.btn.btn-sm i{font-size:12px}.btn.btn-success{background:#099885}.btn.btn-success:hover{background:#4a9c3b}.btn.btn-primary{background:#6690f4}.btn.btn-primary:hover{background:#3164db}.btn.btn-danger{background:#cc563d}.btn.btn-danger:hover{background:#b30000}.hide{display:none}.form-error{color:#cc563d;font-size:13px}.input-group{margin-bottom:10px}.form-field{margin-bottom:15px}.form-field label{display:block;font-size:13px;font-weight:600;margin-bottom:4px;color:#4e5e6a}.password-wrap{position:relative}.password-wrap .form-control{padding-right:40px}.password-wrap .password-eye{position:absolute;right:10px;top:50%;transform:translateY(-50%);color:#999;text-decoration:none;z-index:2}.password-wrap .password-eye:hover{color:#333}input[type=checkbox]{border:1px solid #cdcdcd}.form-control{border:1px solid #cdcdcd;border-radius:6px;height:35px;width:100%;padding:5px;font-family:"Open Sans",sans-serif}.form-control option{padding:5px}.form-control:focus{border:1px solid #6690f4;outline:none}.unlogged{background:#eef1f9;display:flex;align-items:center;justify-content:center;height:100vh}.unlogged .box-login{background:#fff;padding:25px;border-radius:6px;width:400px}.unlogged .box-login .title{text-align:center;padding:10px 10px 25px;border-bottom:1px solid #cdcdcd;font-size:20px;margin-bottom:25px}.sidebar{position:fixed;top:0;left:0;width:220px;height:100vh;background:#1e2a3a;display:flex;flex-direction:column;z-index:1000;transition:width .3s ease;overflow:hidden}.sidebar.collapsed{width:60px}.sidebar.collapsed .sidebar-header .sidebar-logo span,.sidebar.collapsed .sidebar-nav ul li a span,.sidebar.collapsed .sidebar-footer span,.sidebar.collapsed .sidebar-footer .sidebar-user span{display:none}.sidebar.collapsed .sidebar-header .sidebar-logo{font-size:0}.sidebar.collapsed .sidebar-header .sidebar-logo::first-letter{font-size:16px}.sidebar.collapsed .sidebar-nav ul li a{justify-content:center;padding:10px}.sidebar.collapsed .sidebar-nav ul li a i{margin-right:0}.sidebar.collapsed .sidebar-nav ul li.has-submenu .submenu-arrow{display:none}.sidebar.collapsed .sidebar-nav ul li.has-submenu .sidebar-submenu{display:none}.sidebar.collapsed .sidebar-footer .sidebar-footer-link,.sidebar.collapsed .sidebar-footer .sidebar-user{justify-content:center;padding:8px 10px}.sidebar.collapsed .sidebar-footer .sidebar-footer-link i,.sidebar.collapsed .sidebar-footer .sidebar-user i{margin-right:0}.sidebar .sidebar-header{display:flex;align-items:center;justify-content:space-between;padding:15px;border-bottom:1px solid hsla(0,0%,100%,.1)}.sidebar .sidebar-header .sidebar-logo{color:#6690f4;text-decoration:none;font-size:16px;white-space:nowrap}.sidebar .sidebar-header .sidebar-logo span{font-weight:700}.sidebar .sidebar-header .sidebar-toggle{cursor:pointer;color:#c2c7d0;font-size:16px;transition:color .2s ease}.sidebar .sidebar-header .sidebar-toggle:hover{color:#fff}.sidebar .sidebar-nav{flex:1;overflow-y:auto;padding:10px 0}.sidebar .sidebar-nav ul{list-style:none;margin:0;padding:0}.sidebar .sidebar-nav ul li a{display:flex;align-items:center;padding:10px 15px;color:#c2c7d0;text-decoration:none;font-size:14px;transition:all .2s ease;white-space:nowrap}.sidebar .sidebar-nav ul li a i{width:20px;text-align:center;margin-right:10px;font-size:15px}.sidebar .sidebar-nav ul li a:hover{background:hsla(0,0%,100%,.08);color:#fff}.sidebar .sidebar-nav ul li.active a{background:hsla(0,0%,100%,.08);color:#fff;font-weight:600}.sidebar .sidebar-nav ul li.has-submenu>a .submenu-arrow{margin-left:auto;font-size:12px;transition:transform .2s ease;width:auto}.sidebar .sidebar-nav ul li.has-submenu.open>a .submenu-arrow{transform:rotate(180deg)}.sidebar .sidebar-nav ul li.has-submenu .sidebar-submenu{max-height:0;overflow:hidden;transition:max-height .25s ease;background:rgba(0,0,0,.15)}.sidebar .sidebar-nav ul li.has-submenu .sidebar-submenu li a{padding:8px 15px 8px 45px;font-size:13px}.sidebar .sidebar-nav ul li.has-submenu .sidebar-submenu li a i{font-size:13px;width:16px}.sidebar .sidebar-nav ul li.has-submenu.open .sidebar-submenu{max-height:200px}.sidebar .sidebar-footer{border-top:1px solid hsla(0,0%,100%,.1);padding:10px 0}.sidebar .sidebar-footer .sidebar-user{display:flex;align-items:center;padding:8px 15px;color:#c2c7d0;font-size:13px;white-space:nowrap;overflow:hidden}.sidebar .sidebar-footer .sidebar-user i{margin-right:10px;color:#6690f4}.sidebar .sidebar-footer .sidebar-footer-link{display:flex;align-items:center;padding:8px 15px;color:#c2c7d0;text-decoration:none;font-size:13px;transition:all .2s ease;white-space:nowrap}.sidebar .sidebar-footer .sidebar-footer-link i{width:20px;text-align:center;margin-right:10px}.sidebar .sidebar-footer .sidebar-footer-link:hover{background:hsla(0,0%,100%,.08);color:#fff}.sidebar .sidebar-footer .sidebar-footer-link.logout{color:#cc563d}.sidebar .sidebar-footer .sidebar-footer-link.logout:hover{color:#e07a66}.content-wrapper{margin-left:220px;min-height:100vh;transition:margin-left .3s ease}.content-wrapper.expanded{margin-left:60px}.top-bar{background:#fff;border-bottom:1px solid #e8e8e8;padding:10px 20px;display:flex;align-items:center}.top-bar .top-bar-left{display:flex;align-items:center;gap:15px}.top-bar .top-bar-left i{cursor:pointer;font-size:18px;color:#4e5e6a}.top-bar .top-bar-left i:hover{color:#000}.main{padding:25px;background:#d9dee2;min-height:calc(100vh - 45px)}.tasks_container{display:grid;grid-template-columns:repeat(5, 1fr);gap:20px}.tasks_container .column{width:100%}.tasks_container .column h2{display:flex;padding:10px;background:#fff;margin-bottom:10px;font-size:15px;font-weight:300;border-radius:3px 3px 0 0;justify-content:space-between;align-items:center}.tasks_container .column h2 i{cursor:pointer}.tasks_container .column.tasks_suspended h2{border-bottom:5px solid #cc563d}.tasks_container .column.tasks_fvat h2{border-bottom:5px solid #a900fc}.tasks_container .column.tasks_new h2{border-bottom:5px solid #ccc}.tasks_container .column.tasks_bulk h2{border-bottom:5px solid #ff8c00}.tasks_container .column.tasks_to_do h2{border-bottom:5px solid #2aaf47}.tasks_container .column.tasks_to_review h2{border-bottom:5px solid #2535c9}.tasks_container .column.tasks_closed h2{border-bottom:5px solid #000}.tasks_container .column ul{list-style-type:none;margin:0;padding:0}.tasks_container .column ul .task{margin-bottom:5px;background:#fff;padding:10px;border-radius:0;display:flex;position:relative;border-radius:6px;flex-wrap:wrap}.tasks_container .column ul .task.notopened{border:2px solid #cc563d}.tasks_container .column ul .task .top{display:flex;justify-content:space-between;margin-bottom:5px;width:100%}.tasks_container .column ul .task .top ._users{display:flex;gap:5px;flex-wrap:wrap}.tasks_container .column ul .task .top ._users .user{display:flex;width:25px;height:25px;border-radius:6px;justify-content:center;align-items:center;color:#fff;font-size:12px}.tasks_container .column ul .task .top ._timer{display:flex;gap:5px}.tasks_container .column ul .task .top ._timer .recursively{color:#fff;background:#405189;border-radius:3px;cursor:pointer;margin-bottom:5px;width:25px;height:25px;text-align:center;display:block}.tasks_container .column ul .task .top ._timer .recursively i{font-size:12px}.tasks_container .column ul .task .top ._timer .task_start{display:block;background:#099885;color:#fff;border-radius:6px;cursor:pointer;margin-bottom:5px;width:25px;height:25px;text-align:center}.tasks_container .column ul .task .top ._timer .task_start.hidden{display:none}.tasks_container .column ul .task .top ._timer .task_start i{font-size:12px}.tasks_container .column ul .task .top ._timer .task_end{background:#cc563d;display:block;color:#fff;border-radius:6px;cursor:pointer;margin-bottom:5px;width:25px;height:25px;text-align:center}.tasks_container .column ul .task .top ._timer .task_end.hidden{display:none}.tasks_container .column ul .task .top ._timer .task_end i{font-size:12px}.tasks_container .column ul .task .middle{width:100%}.tasks_container .column ul .task .name{font-size:14px;color:#333;text-decoration:none;display:block;margin-bottom:5px}.tasks_container .column ul .task .bottom{display:flex;justify-content:space-between}.tasks_container .column ul .task .client_info,.tasks_container .column ul .task .current_status{font-size:12px;font-weight:400}.tasks_container .column ul .task .client_info strong,.tasks_container .column ul .task .current_status strong{font-weight:600}.tasks_container .column ul .task .current_status{position:relative;cursor:pointer}.tasks_container .column ul .task .current_status .status_change{position:absolute;left:0;top:20px;background:#fff;padding:15px;border:1px solid #dfdfdf;border-radius:3px;cursor:pointer;box-shadow:0 0 15px rgba(0,0,0,.1);z-index:99;display:none}.tasks_container .column ul .task .current_status .status_change select{width:250px;padding:10px;border:1px solid #cdcdcd;border-radius:3px}.tasks_container .column ul .task .current_status .status_change select option{font-size:15px;padding:3px}.tasks_container .column ul .task .dates{margin-bottom:5px;display:flex;justify-content:space-between;font-size:12px}.tasks_container .column ul .task .dates .danger{color:#cc563d;font-weight:600}.tasks_container .column ul .task .dates .warning{color:#ff8c00}.tasks_container .column ul .task .dates i{font-size:12px;color:#c9ced4;margin-right:5px}.block-header{margin-bottom:20px}.block-header h2{font-size:20px;font-weight:400;color:#4e5e6a;margin:0;padding-bottom:12px;border-bottom:2px solid #e2e6ec}.block-header h2 strong{font-weight:700}.filters-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:24px;padding:12px 16px;background:#f5f7fa;border-radius:8px;border:1px solid #e2e6ec}.filters-bar select,.filters-bar input[type=text],.filters-bar input[type=date],.filters-bar input[type=number]{height:36px;min-width:170px;padding:0 10px;border:1px solid #d0d5dd;border-radius:6px;background:#fff;font-size:13px;color:#4e5e6a;font-family:"Open Sans",sans-serif;transition:border-color .2s}.filters-bar select:focus,.filters-bar input[type=text]:focus,.filters-bar input[type=date]:focus,.filters-bar input[type=number]:focus{border-color:#6690f4;outline:none}.filters-bar .btn{height:36px;display:inline-flex;align-items:center;gap:5px;padding:0 14px;border-radius:6px;font-size:13px;font-weight:500;border:none;cursor:pointer;transition:background .2s,box-shadow .2s;text-decoration:none;color:#fff}.filters-bar .btn.btn-primary{background:#6690f4}.filters-bar .btn.btn-primary:hover{background:#4a74d4}.filters-bar .btn.btn-success{background:#099885}.filters-bar .btn.btn-success:hover{background:#077a6b}.section-title{font-size:14px;font-weight:600;color:#4e5e6a;margin:28px 0 12px;padding-bottom:8px;border-bottom:1px solid #e2e6ec}.action_menu{display:flex;margin-bottom:25px;gap:20px}.action_menu .btn{display:inline-flex;padding:7px 15px;color:#fff;text-decoration:none;align-items:center;justify-content:center;gap:5px}.action_menu .btn.btn_add{background:#099885}.action_menu .btn.btn_add:hover{background:#4a9c3b}.action_menu .btn.btn_cancel{background:#cc563d}.action_menu .btn.btn_cancel:hover{background:#b30000}.action_menu .btn.disabled{opacity:.5}.form_container{background:#fff;padding:25px;max-width:1300px}.form_container.full{max-width:100%}.form_container .form_group{margin-bottom:10px;display:flex}.form_container .form_group>.label{width:300px;display:inline-flex;align-items:flex-start;justify-content:right;padding-right:10px}.form_container .form_group .input{width:calc(100% - 300px)}.fullscreen_description{position:fixed !important;top:25px;left:25px;right:25px;bottom:25px;z-index:9999;background:#fff;padding:20px;overflow:auto;border-radius:.25rem;box-shadow:0 0 20px rgba(0,0,0,.3)}.fullscreen{position:absolute;top:10px;right:10px;cursor:pointer;color:#fff;background:#cc563d;display:inline-flex;height:40px;width:40px;border-radius:6px;align-items:center;justify-content:center;transition:all .3s ease}.fullscreen:hover{transform:scale(1.05);text-decoration:none}.task_popup{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.5);display:none;z-index:9999}.task_popup .task_details{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);background:#fff;padding:25px;border-radius:6px;max-width:1140px;width:100%;transition:all .3s ease;height:90vh}.task_popup .task_details .content{height:calc(100% - 50px)}.task_popup .task_details.open_works_time{max-width:1540px}.task_popup .task_details.open_works_time .content{grid-template-columns:1fr 300px 350px}.task_popup .task_details.open_works_time .content .task_work_details{display:block}.task_popup .task_details .title{font-size:20px;margin-bottom:25px;display:flex;align-items:center;gap:10px}.task_popup .task_details .title a{border:1px solid #099885;display:inline-flex;height:30px;width:30px;border-radius:6px;align-items:center;justify-content:center}.task_popup .task_details .title a:hover{text-decoration:none}.task_popup .task_details .title a i{color:#099885}.task_popup .task_details .title a.task-delete{border:1px solid #cc563d}.task_popup .task_details .title a.task-delete i{color:#cc563d}.task_popup .task_details .title a i{font-size:14px}.task_popup .task_details .title .task-title-edit-box{align-items:center;gap:6px}.task_popup .task_details .title .task-title-edit-box .task-title-input{height:30px;font-size:14px;padding:2px 8px;width:300px;border:1px solid #ccc;border-radius:4px}.task_popup .task_details .title .task-title-edit-box a.task-title-save,.task_popup .task_details .title .task-title-edit-box a.task-title-cancel{height:30px;width:30px;display:inline-flex;align-items:center;justify-content:center;border-radius:6px}.task_popup .task_details .title .task-title-edit-box a.task-title-save i,.task_popup .task_details .title .task-title-edit-box a.task-title-cancel i{font-size:13px}.task_popup .task_details .title .task-title-edit-box a.task-title-save{background:#099885;border-color:#099885}.task_popup .task_details .title .task-title-edit-box a.task-title-save i{color:#fff}.task_popup .task_details .title .task-title-edit-box a.task-title-cancel{background:#cc563d;border-color:#cc563d}.task_popup .task_details .title .task-title-edit-box a.task-title-cancel i{color:#fff}.task_popup .task_details .close{position:absolute;top:10px;right:10px;cursor:pointer}.task_popup .task_details .content{display:grid;font-size:14px;grid-template-columns:1fr 300px;gap:30px;transition:all .3s ease}.task_popup .task_details .content h3{width:100%;margin-top:0;margin-bottom:5px;font-weight:500;color:#000;font-size:17px}.task_popup .task_details .content .left{height:100%;overflow:hidden}.task_popup .task_details .content .left .users{display:flex;gap:20px}.task_popup .task_details .content .left .users .user{display:flex;gap:10px;align-items:center;margin-bottom:10px}.task_popup .task_details .content .left .users .user .avatar{height:30px;width:30px;border-radius:6px;background:#ccc;display:flex;justify-content:center;align-items:center;color:#fff;font-size:12px}.task_popup .task_details .content .left .comments{border-radius:3px;max-height:406px;overflow-y:auto}.task_popup .task_details .content .left .comments .new_comment{margin-bottom:10px}.task_popup .task_details .content .left .comments .new_comment textarea{height:75px;margin-bottom:10px;border-radius:6px}.task_popup .task_details .content .left .comments .new_comment .add_comment{background:#099885;color:#fff;padding:10px;border-radius:6px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;width:200px;text-decoration:none}.task_popup .task_details .content .left .comments .new_comment .add_comment:hover{background:#4a9c3b}.task_popup .task_details .content .left .comments ul{margin:0;padding:0;list-style-type:none}.task_popup .task_details .content .left .comments ul li{background:#ced4da;margin-bottom:5px;padding:15px;border-radius:6px;position:relative}.task_popup .task_details .content .left .comments ul li .delete_comment{position:absolute;top:10px;right:10px;cursor:pointer;color:#cc563d}.task_popup .task_details .content .left .comments ul li .author{font-weight:600;margin-bottom:5px;display:inline-flex;margin-right:10px}.task_popup .task_details .content .left .comments ul li .date{font-size:12px;margin-bottom:5px;display:inline-flex}.task_popup .task_details .content .left .comments ul li .text{margin-bottom:15px;font-size:13px}.task_popup .task_details .content .left .checklist{border-radius:3px;margin-bottom:10px}.task_popup .task_details .content .left .checklist .new_element{display:flex;margin-bottom:10px}.task_popup .task_details .content .left .checklist .new_element input{border-radius:6px 0 0 6px}.task_popup .task_details .content .left .checklist .new_element a{display:flex;align-items:center;justify-content:center;padding:10px;border-radius:0 6px 6px 0;text-decoration:none;width:35px;background:#099885;color:#fff}.task_popup .task_details .content .left .checklist ul{margin:0;padding:0;list-style-type:none;overflow-y:auto;max-height:calc(90vh - 400px)}.task_popup .task_details .content .left .checklist ul li{display:flex;gap:10px;margin-bottom:5px;background:#fff;border-radius:3px;padding:10px;border:1px solid #cdcdcd;font-size:13px;align-items:flex-start}.task_popup .task_details .content .left .checklist ul li a{margin-left:auto;margin-right:0;cursor:pointer;background:#cc563d;display:flex;height:25px;width:25px;min-width:25px;justify-content:center;align-items:center;border:0;border-radius:3px;transition:all .3s ease}.task_popup .task_details .content .left .checklist ul li a:hover{text-decoration:none;background:#b30000}.task_popup .task_details .content .left .checklist ul li a i{color:#fff;font-size:12px}.task_popup .task_details .content .left .attachments{margin-top:10px;border:1px solid #e6e9ed;border-radius:8px;padding:12px;background:#f9fbfd}.task_popup .task_details .content .left .attachments h3{margin-bottom:10px;font-size:16px;font-weight:600}.task_popup .task_details .content .left .attachments .attachments_upload{display:flex;gap:10px;align-items:center;margin-bottom:10px}.task_popup .task_details .content .left .attachments .attachments_upload .attachment_file_input{flex:1;margin-bottom:0;border-radius:6px;background:#fff}.task_popup .task_details .content .left .attachments .attachments_upload .attachment-upload-btn{white-space:nowrap;border-radius:6px;min-width:150px}.task_popup .task_details .content .left .attachments .attachments_upload .attachment-upload-btn.is-loading{pointer-events:none;opacity:.85}.task_popup .task_details .content .left .attachments .attachments_upload .attachment-upload-btn.is-loading i{margin-right:6px}.task_popup .task_details .content .left .attachments .attachments_list{margin:0;padding:0;list-style:none;display:grid;gap:8px;max-height:180px;overflow-y:auto}.task_popup .task_details .content .left .attachments .attachments_list li{display:flex;align-items:center;gap:8px;background:#fff;border:1px solid #e4e8ee;border-radius:6px;padding:8px 10px}.task_popup .task_details .content .left .attachments .attachments_list li .attachment-link{color:#1f3d72;text-decoration:none;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:calc(100% - 140px)}.task_popup .task_details .content .left .attachments .attachments_list li .attachment-link:hover{text-decoration:underline}.task_popup .task_details .content .left .attachments .attachments_list li small{color:#6b7280;margin-right:auto}.task_popup .task_details .content .left .attachments .attachments_list li .attachment-rename,.task_popup .task_details .content .left .attachments .attachments_list li .attachment-delete{display:inline-flex;align-items:center;justify-content:center;height:28px;width:28px;border-radius:4px;text-decoration:none;transition:all .2s ease}.task_popup .task_details .content .left .attachments .attachments_list li .attachment-rename{border:1px solid #d8e2f6;color:#6690f4;background:#f4f8ff}.task_popup .task_details .content .left .attachments .attachments_list li .attachment-rename:hover{background:#e7f0ff}.task_popup .task_details .content .left .attachments .attachments_list li .attachment-delete{border:1px solid #f1d3d1;color:#cc563d;background:#fff6f6}.task_popup .task_details .content .left .attachments .attachments_list li .attachment-delete:hover{background:#ffeaea}.task_popup .task_details .content .left .attachments .attachments_list .attachments-empty{color:#6b7280;border-style:dashed;justify-content:center;font-size:13px}.task_popup .task_details .content .left .description{padding:15px;border-radius:.25rem;border:1px solid #cdcdcd;margin-bottom:15px;max-height:202px;overflow-x:hidden;position:relative}.task_popup .task_details .content .right .box{margin-bottom:15px}.task_popup .task_details .content .right .time a.time_worked_toggle{color:#299cdb;display:inline-flex;border:1px solid #299cdb}.task_popup .task_details .content .right .time a.time_worked_toggle:hover{background:#dff0fa;text-decoration:none}.task_popup .task_details .content .right .time a.time_worked_toggle:active,.task_popup .task_details .content .right .time a.time_worked_toggle:focus{text-decoration:none}.task_popup .task_details .content .right .time a:not(.time_worked_toggle){margin-top:10px;text-decoration:none;gap:10px}.task_popup .task_details .content .right .time a:not(.time_worked_toggle).task_start{background:#0ab39c;color:#fff}.task_popup .task_details .content .right .time a:not(.time_worked_toggle).task_start:hover{background:#099885}.task_popup .task_details .content .right .time a:not(.time_worked_toggle).task_end{background:#cc563d;color:#fff}.task_popup .task_details .content .right .time a:not(.time_worked_toggle).hidden{display:none}.task_popup .task_details .content .right .dates{display:flex;justify-content:space-between;flex-wrap:wrap}.task_popup .task_details .content .right .dates .danger{color:#cc563d;font-weight:600}.task_popup .task_details .content .right .dates .warning{color:#ff8c00}.task_popup .task_details .content .right .dates i{color:#c9ced4;margin-right:5px}.task_popup .task_details .content .task_work_details{display:none;overflow-y:auto;max-height:508px;width:100%;padding-right:10px;padding-top:4px}.task_popup .task_details .content .task_work_details ._line{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;margin-bottom:5px}.task_popup .task_details .content .task_work_details ._line ._user{width:100%;font-size:13px}.task_popup .task_details .content .task_work_details ._line input{width:calc(50% - 25px);text-align:center;margin-left:2px;margin-right:2px}.task_popup .task_details .content .task_work_details ._work_delete{display:inline-flex;height:35px;width:35px;border-radius:6px;align-items:center;justify-content:center;cursor:pointer;border:1px solid #cc563d;margin-left:2px;transition:all .3s ease}.task_popup .task_details .content .task_work_details ._work_delete:hover{background:#cc563d}.task_popup .task_details .content .task_work_details ._work_delete:hover i{color:#fff}.task_popup .task_details .content .task_work_details ._work_delete i{transition:all .3s ease;color:#cc563d}.table{width:100%;border:none;border-radius:8px;overflow:hidden;box-shadow:0 1px 3px rgba(0,0,0,.06);background:#fff}.table th,.table td{padding:10px 14px;border:none;border-bottom:1px solid #eef0f3;text-align:left;vertical-align:middle}.table thead th{background:#f5f7fa;color:#4e5e6a;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.3px;white-space:nowrap;border-bottom:2px solid #e2e6ec}.table tbody tr{transition:background .15s ease}.table tbody tr:last-child td{border-bottom:none}.table tbody tr:hover{background:#f8fafd}.table td.center,.table th.center{text-align:center}.table td.left,.table th.left{text-align:left}.table td.right,.table th.right{text-align:right}.table td[colspan]{text-align:center;color:#8896a4;padding:24px 14px;font-style:italic}.projects_container{background:#fff;padding:15px;border-radius:6px;display:flex;gap:20px}.projects_container .left{width:calc(100% - 250px)}.projects_container .left ._projects,.projects_container .left ._users{display:flex;gap:20px;flex-wrap:wrap}.projects_container .right{width:250px;display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:center;gap:20px;border-left:1px solid #cdcdcd;padding-left:15px}.projects_container .right select{width:200px}.default_popup{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.5);display:none}.default_popup .popup_content{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);background:#fff;padding:25px;border-radius:0;max-width:1140px;width:100%}.default_popup .popup_content .close{position:absolute;top:10px;right:10px;cursor:pointer}#fg-cron{margin:10px 0}#fg-cron .countdown{background:#099885;color:#fff;padding:10px}#fg-cron #cron-container{max-height:300px;overflow-x:hidden;overflow-y:auto}#fg-cron #cron-container .msg{font-size:13px;padding:5px;border-bottom:1px solid #e8e8e8}.card{background:#fff;padding:25px;border-radius:6px;color:#000;font-size:15px;max-width:1280px}.card.mb25{margin-bottom:25px}.card .card-header{font-weight:600}.card .card-body{padding-top:10px}.card .card-body table{border-collapse:collapse}.card .card-body table th,.card .card-body table td{font-size:14px}.card .card-body table th.bold,.card .card-body table td.bold{font-weight:600}.card .card-body table th.text-right,.card .card-body table td.text-right{text-align:right}.card .card-body table th.text-center,.card .card-body table td.text-center{text-align:center}.card .card-body table th .close-task,.card .card-body table td .close-task{text-decoration:none;color:#6690f4}.card .card-body table th .close-task:hover,.card .card-body table td .close-task:hover{color:#cc563d}.finance-summary{display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:10px}.finance-summary .panel{background:#fff;border-radius:6px;padding:15px}.finance-summary .panel h1{font-size:20px;margin:0}.finance-summary .panel span{font-size:.85em}.finance-manager{display:grid;gap:10px;grid-template-columns:250px 1fr 500px;padding-top:25px}.finance-manager .manage-menu{display:inline-block;margin-right:10px}.finance-manager .manage-menu a{color:#333;text-decoration:none;font-weight:300;display:block}.finance-manager .actions{width:100px;text-align:center}.finance-manager .actions a{display:inline-flex;margin:0 2px;height:25px;width:25px;align-items:center;justify-content:center;text-decoration:none;color:#000;border:1px solid #e7e7e7;font-size:11px;border-radius:3px;transition:all .3s ease}.finance-manager .actions a:hover{border:1px solid #6690f4}.bootstrap-tagsinput .tag{background:#6690f4;font-size:13px;padding:5px 10px;border-radius:12px}.bootstrap-tagsinput .tag [data-role=remove]{color:#fff !important}.bootstrap-tagsinput .tag [data-role=remove]:hover{box-shadow:none !important;color:#000 !important}.finance-tags{display:flex;flex-wrap:wrap;gap:5px}.finance-tags a:not(.btn){display:flex;width:100%;text-decoration:none;color:#4e5e6a}.finance-tags a:not(.btn).zoom-100{font-size:1.2em}.finance-tags a:not(.btn).zoom-90{font-size:1.15em}.finance-tags a:not(.btn).zoom-80{font-size:1.1em}.finance-tags a:not(.btn).zoom-70{font-size:1.05em}.finance-tags a:not(.btn).zoom-60{font-size:1em}.finance-tags a:not(.btn).zoom-50{font-size:.95em}.finance-tags a:not(.btn).zoom-40{font-size:.9em}.finance-tags a:not(.btn).zoom-30{font-size:.85em}.finance-tags a:not(.btn).zoom-20{font-size:.8em}.finance-tags a:not(.btn).zoom-10{font-size:.75em}.finance-tags a:not(.btn).zoom-0{font-size:.7em}.manage-menu{position:relative}.manage-menu .context-menu{border-left:4px dotted #000;width:1px;height:100%}.manage-menu .context-menu-container{position:absolute;display:none;background:#fff;box-shadow:5px 5px 15px rgba(0,0,0,.1);top:2px;left:2px}.manage-menu .context-menu-container ul{list-style-type:none;margin:0;padding:0}.manage-menu .context-menu-container ul li a{display:block;padding:7px 15px;white-space:nowrap}.manage-menu .context-menu-container ul li a:hover{background:#f8f8f8}.manage-menu:hover .context-menu-container{display:block}.wiki-categories{display:grid;gap:10px;margin-top:25px;grid-template-columns:1fr 1fr 1fr 1fr}.wiki-categories .category{background:#fff;padding:10px}.wiki-categories .category .users{display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:5px}.wiki-categories .category .users .user{display:flex;height:25px;width:25px;border-radius:50%;background:#ccc;justify-content:center;align-items:center;color:#fff;font-size:12px}.wiki-categories .category .actions{display:grid;grid-template-columns:1fr 1fr}.wiki-categories .category .actions a{display:block;color:#4e5e6a;font-size:13px;text-align:center}.wiki-categories .category .title{margin-bottom:5px}.wiki-categories .category .title a{display:block;color:#4e5e6a;font-size:13px;font-weight:600}.bootstrap-datetimepicker-widget .picker-switch a{display:block;color:#000}.gantt_users{display:flex;gap:20px}#g-results{background:#fff;padding:25px}.g-menu-container{margin-bottom:15px}.g-menu-container .right-menu{display:none}.g-center{text-align:center}.alert{background:#099885;border:0;color:#fff}.tasks_main_view{display:flex;gap:20px;align-items:flex-start}.tasks_main_view ._left_column{width:-moz-fit-content;width:fit-content;min-width:350px;max-width:520px;padding:0;background:rgba(0,0,0,0);border-right:0}.tasks_main_view ._left_column .filters_panel{background:linear-gradient(180deg, #fdfefe 0%, #f4f7fb 100%);border:1px solid #dbe2ea;border-radius:12px;padding:16px;box-shadow:none}.tasks_main_view ._left_column .filters_panel_header{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}.tasks_main_view ._left_column .filters_panel_title{display:flex;align-items:center;gap:8px}.tasks_main_view ._left_column .filters_panel_title i{color:#1f3d72}.tasks_main_view ._left_column .filters_panel_title h3{margin:0;font-size:16px;font-weight:700;color:#1f3d72}.tasks_main_view ._left_column .active_filters_badge{display:inline-flex;align-items:center;padding:4px 10px;border-radius:999px;font-size:12px;color:#425466;background:#e9eff8}.tasks_main_view ._left_column .active_filters_badge strong{margin-left:4px;font-size:13px;color:#1f3d72}.tasks_main_view ._left_column .filters_controls{margin-bottom:14px;padding:12px;border-radius:10px;border:1px solid #dbe2ea;background:#fff}.tasks_main_view ._left_column .filters_label{display:block;margin-bottom:6px;font-size:12px;font-weight:600;color:#425466}.tasks_main_view ._left_column select[name=filtr]{margin-bottom:12px;height:40px;border-color:#d1dae4}.tasks_main_view ._left_column select[name=filtr]:focus{border-color:#5f88e9;box-shadow:0 0 0 3px rgba(95,136,233,.15)}.tasks_main_view ._left_column ._buttons{display:flex;gap:8px}.tasks_main_view ._left_column ._buttons .btn{flex:1;min-height:34px;font-size:12px;text-transform:uppercase;letter-spacing:.3px}.tasks_main_view ._left_column ._buttons .btn-dark{background:#3d495e}.tasks_main_view ._left_column ._buttons .btn-dark:hover{background:#2f394c}.tasks_main_view ._left_column .filters_section{border:1px solid #dbe2ea;border-radius:10px;background:#fff;margin-bottom:12px;overflow:hidden}.tasks_main_view ._left_column .filters_section_header{display:flex;gap:8px;align-items:center;justify-content:space-between;padding:10px 12px;background:#f4f7fb;border-bottom:1px solid #e3eaf2}.tasks_main_view ._left_column .filters_section_header h4{margin:0;font-size:14px;font-weight:700;color:#243447}.tasks_main_view ._left_column .filters_section_header .filters_search{max-width:170px;height:32px;font-size:12px;padding:4px 10px;border-color:#d2dbe6}.tasks_main_view ._left_column .filters_section_list{max-height:270px;overflow-y:auto;padding:6px}.tasks_main_view ._left_column .filters_section._projects .filters_section_list{max-height:none;overflow:visible}.tasks_main_view ._left_column .filters_item{border-radius:8px;transition:background .2s ease}.tasks_main_view ._left_column .filters_item:hover{background:#f4f7fb}.tasks_main_view ._left_column .project_row,.tasks_main_view ._left_column ._user{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:5px 7px}.tasks_main_view ._left_column .project_row label,.tasks_main_view ._left_column ._user label{margin:0;flex:1;font-weight:400;font-size:14px;white-space:nowrap}.tasks_main_view ._left_column .project_count{display:inline-block;margin-left:4px;min-width:26px;padding:0 7px;border-radius:999px;background:#1f3d72;color:#fff;font-weight:700;font-size:11px;line-height:19px;text-align:center;vertical-align:middle}.tasks_main_view ._left_column .project_delete_inline{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:5px;border:1px solid #cc563d;background:#cc563d;color:#fff;text-decoration:none;transition:all .2s ease;margin:1px 0}.tasks_main_view ._left_column .project_delete_inline:hover{background:#b74831;border-color:#b74831}.tasks_main_view ._left_column .project_delete_inline i{font-size:10px}.tasks_main_view ._right_column{flex:1;max-width:none;min-width:0}@media(max-width: 1200px){.tasks_main_view{flex-direction:column}.tasks_main_view ._left_column,.tasks_main_view ._right_column{max-width:100%;width:100%}}.gantt-target .gantt-container.gantt-draggable{cursor:grab}.gantt-target .gantt-container.gantt-dragging{cursor:grabbing}#billing-summary .card-header{padding:10px}#billing-summary .billing-kpi{border:1px solid #dee2e6;border-radius:6px;padding:10px 12px;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.04)}#billing-summary .billing-kpi-label{font-size:12px;color:#6c757d;margin-bottom:3px}#billing-summary .billing-kpi-value{font-size:21px;font-weight:700;line-height:1.1}#billing-summary .billing-details-row{display:none}#billing-summary .billing-client-name{font-weight:600}#billing-summary .billing-table>thead>tr>th{background:#f8f9fa}#billing-summary .billing-details-wrap{background:#f8fbff}.vacation-type-badge{display:inline-block;padding:2px 8px;border-radius:4px;font-size:12px;font-weight:500;background:#e3f0ff;color:#2563eb}.vacation-type-badge.type-chorobowe{background:#fff3e0;color:#e65100}.vacation-type-badge.type-inna_nieobecnosc{background:#f3e5f5;color:#7b1fa2}/*# sourceMappingURL=style.css.map */ \ No newline at end of file diff --git a/layout/style.css.map b/layout/style.css.map index 48ce7f3..4a6ae0d 100644 --- a/layout/style.css.map +++ b/layout/style.css.map @@ -1 +1 @@ -{"version":3,"sources":["style.scss"],"names":[],"mappings":"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","file":"style.css","sourcesContent":["$cBlue: #6690F4;\r\n$cRed: #cc563d;\r\n$cGreen: #099885;\r\n$cBlack: #4e5e6a;\r\n\r\n.default-btn {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 40px;\r\n border-radius: 6px;\r\n padding: 0 15px;\r\n transition: all .3s ease;\r\n\r\n &:hover {\r\n text-decoration: none;\r\n }\r\n}\r\n\r\n.animate {\r\n animation: mymove 3s infinite;\r\n}\r\n\r\n.text-right {\r\n text-align: right;\r\n}\r\n\r\n.nowrap {\r\n white-space: nowrap;\r\n}\r\n\r\ntable {\r\n border-collapse: collapse;\r\n font-size: 13px;\r\n}\r\n\r\nsmall {\r\n font-size: .75em;\r\n}\r\n\r\n@keyframes mymove {\r\n 50% {\r\n opacity: .33;\r\n }\r\n}\r\n\r\n/* motion */\r\n@keyframes gradient-animation {\r\n 0% {\r\n background-position: 15% 0%;\r\n }\r\n\r\n 50% {\r\n background-position: 85% 100%;\r\n }\r\n\r\n 100% {\r\n background-position: 15% 0%;\r\n }\r\n}\r\n\r\n@keyframes frame-enter {\r\n 0% {\r\n clip-path: polygon(0% 100%, 3px 100%, 3px 3px, calc(100% - 3px) 3px, calc(100% - 3px) calc(100% - 3px), 3px calc(100% - 3px), 3px 100%, 100% 100%, 100% 0%, 0% 0%);\r\n }\r\n\r\n 25% {\r\n clip-path: polygon(0% 100%, 3px 100%, 3px 3px, calc(100% - 3px) 3px, calc(100% - 3px) calc(100% - 3px), calc(100% - 3px) calc(100% - 3px), calc(100% - 3px) 100%, 100% 100%, 100% 0%, 0% 0%);\r\n }\r\n\r\n 50% {\r\n clip-path: polygon(0% 100%, 3px 100%, 3px 3px, calc(100% - 3px) 3px, calc(100% - 3px) 3px, calc(100% - 3px) 3px, calc(100% - 3px) 3px, calc(100% - 3px) 3px, 100% 0%, 0% 0%);\r\n }\r\n\r\n 75% {\r\n -webkit-clip-path: polygon(0% 100%, 3px 100%, 3px 3px, 3px 3px, 3px 3px, 3px 3px, 3px 3px, 3px 3px, 3px 0%, 0% 0%);\r\n }\r\n\r\n 100% {\r\n -webkit-clip-path: polygon(0% 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 0% 100%);\r\n }\r\n}\r\n\r\n* {\r\n box-sizing: border-box;\r\n}\r\n\r\nbody {\r\n font-family: \"Open Sans\", sans-serif;\r\n margin: 0;\r\n padding: 0;\r\n font-size: 15px;\r\n color: #4e5e6a;\r\n}\r\n\r\n.btn {\r\n padding: 9px 25px;\r\n transition: all 0.3s ease;\r\n color: #FFF;\r\n border: 0;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n display: inline-flex;\r\n text-decoration: none;\r\n gap: 5px;\r\n justify-content: center;\r\n align-items: center;\r\n\r\n &.btn_small,\r\n &.btn-xs,\r\n &.btn-sm {\r\n padding: 5px 7px;\r\n font-size: 13px;\r\n\r\n i {\r\n font-size: 12px;\r\n }\r\n }\r\n\r\n &.btn-success {\r\n background: $cGreen;\r\n\r\n &:hover {\r\n background: #4a9c3b;\r\n }\r\n }\r\n\r\n &.btn-primary {\r\n background: $cBlue;\r\n\r\n &:hover {\r\n background: #3164db;\r\n }\r\n }\r\n\r\n &.btn-danger {\r\n background: $cRed;\r\n\r\n &:hover {\r\n background: #b30000;\r\n }\r\n }\r\n}\r\n\r\n.hide {\r\n display: none;\r\n}\r\n\r\n.form-error {\r\n color: $cRed;\r\n font-size: 13px;\r\n}\r\n\r\n.input-group {\r\n margin-bottom: 10px;\r\n}\r\n\r\n.form-field {\r\n margin-bottom: 15px;\r\n\r\n label {\r\n display: block;\r\n font-size: 13px;\r\n font-weight: 600;\r\n margin-bottom: 4px;\r\n color: #4e5e6a;\r\n }\r\n}\r\n\r\n.password-wrap {\r\n position: relative;\r\n\r\n .form-control {\r\n padding-right: 40px;\r\n }\r\n\r\n .password-eye {\r\n position: absolute;\r\n right: 10px;\r\n top: 50%;\r\n transform: translateY(-50%);\r\n color: #999;\r\n text-decoration: none;\r\n z-index: 2;\r\n\r\n &:hover {\r\n color: #333;\r\n }\r\n }\r\n}\r\n\r\ninput[type=\"checkbox\"] {\r\n border: 1px solid #cdcdcd;\r\n}\r\n\r\n.form-control {\r\n border: 1px solid #cdcdcd;\r\n border-radius: 6px;\r\n height: 35px;\r\n width: 100%;\r\n padding: 5px;\r\n font-family: \"Open Sans\", sans-serif;\r\n\r\n option {\r\n padding: 5px;\r\n }\r\n\r\n &:focus {\r\n border: 1px solid $cBlue;\r\n outline: none;\r\n }\r\n}\r\n\r\n.unlogged {\r\n background: #EEF1F9;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100vh;\r\n\r\n .box-login {\r\n background: #FFF;\r\n padding: 25px;\r\n border-radius: 6px;\r\n width: 400px;\r\n\r\n .title {\r\n text-align: center;\r\n padding: 10px 10px 25px;\r\n border-bottom: 1px solid #cdcdcd;\r\n font-size: 20px;\r\n margin-bottom: 25px;\r\n }\r\n }\r\n}\r\n\r\n$sidebar-width: 220px;\r\n$sidebar-collapsed-width: 60px;\r\n$sidebar-bg: #1e2a3a;\r\n$sidebar-text: #c2c7d0;\r\n$sidebar-active: #fff;\r\n$sidebar-hover-bg: rgba(255, 255, 255, 0.08);\r\n\r\n.sidebar {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n width: $sidebar-width;\r\n height: 100vh;\r\n background: $sidebar-bg;\r\n display: flex;\r\n flex-direction: column;\r\n z-index: 1000;\r\n transition: width 0.3s ease;\r\n overflow: hidden;\r\n\r\n &.collapsed {\r\n width: $sidebar-collapsed-width;\r\n\r\n .sidebar-header .sidebar-logo span,\r\n .sidebar-nav ul li a span,\r\n .sidebar-footer span,\r\n .sidebar-footer .sidebar-user span {\r\n display: none;\r\n }\r\n\r\n .sidebar-header .sidebar-logo {\r\n font-size: 0;\r\n\r\n &::first-letter {\r\n font-size: 16px;\r\n }\r\n }\r\n\r\n .sidebar-nav ul li a {\r\n justify-content: center;\r\n padding: 10px;\r\n\r\n i {\r\n margin-right: 0;\r\n }\r\n }\r\n\r\n .sidebar-nav ul li.has-submenu {\r\n .submenu-arrow {\r\n display: none;\r\n }\r\n\r\n .sidebar-submenu {\r\n display: none;\r\n }\r\n }\r\n\r\n .sidebar-footer .sidebar-footer-link,\r\n .sidebar-footer .sidebar-user {\r\n justify-content: center;\r\n padding: 8px 10px;\r\n\r\n i {\r\n margin-right: 0;\r\n }\r\n }\r\n }\r\n\r\n .sidebar-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 15px;\r\n border-bottom: 1px solid rgba(255, 255, 255, 0.1);\r\n\r\n .sidebar-logo {\r\n color: $cBlue;\r\n text-decoration: none;\r\n font-size: 16px;\r\n white-space: nowrap;\r\n\r\n span {\r\n font-weight: 700;\r\n }\r\n }\r\n\r\n .sidebar-toggle {\r\n cursor: pointer;\r\n color: $sidebar-text;\r\n font-size: 16px;\r\n transition: color 0.2s ease;\r\n\r\n &:hover {\r\n color: #fff;\r\n }\r\n }\r\n }\r\n\r\n .sidebar-nav {\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 10px 0;\r\n\r\n ul {\r\n list-style: none;\r\n margin: 0;\r\n padding: 0;\r\n\r\n li {\r\n a {\r\n display: flex;\r\n align-items: center;\r\n padding: 10px 15px;\r\n color: $sidebar-text;\r\n text-decoration: none;\r\n font-size: 14px;\r\n transition: all 0.2s ease;\r\n white-space: nowrap;\r\n\r\n i {\r\n width: 20px;\r\n text-align: center;\r\n margin-right: 10px;\r\n font-size: 15px;\r\n }\r\n\r\n &:hover {\r\n background: $sidebar-hover-bg;\r\n color: $sidebar-active;\r\n }\r\n }\r\n\r\n &.active a {\r\n background: $sidebar-hover-bg;\r\n color: $sidebar-active;\r\n font-weight: 600;\r\n }\r\n\r\n &.has-submenu {\r\n >a .submenu-arrow {\r\n margin-left: auto;\r\n font-size: 12px;\r\n transition: transform 0.2s ease;\r\n width: auto;\r\n }\r\n\r\n &.open>a .submenu-arrow {\r\n transform: rotate(180deg);\r\n }\r\n\r\n .sidebar-submenu {\r\n max-height: 0;\r\n overflow: hidden;\r\n transition: max-height 0.25s ease;\r\n background: rgba(0, 0, 0, 0.15);\r\n\r\n li a {\r\n padding: 8px 15px 8px 45px;\r\n font-size: 13px;\r\n\r\n i {\r\n font-size: 13px;\r\n width: 16px;\r\n }\r\n }\r\n }\r\n\r\n &.open .sidebar-submenu {\r\n max-height: 200px;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n .sidebar-footer {\r\n border-top: 1px solid rgba(255, 255, 255, 0.1);\r\n padding: 10px 0;\r\n\r\n .sidebar-user {\r\n display: flex;\r\n align-items: center;\r\n padding: 8px 15px;\r\n color: $sidebar-text;\r\n font-size: 13px;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n\r\n i {\r\n margin-right: 10px;\r\n color: $cBlue;\r\n }\r\n }\r\n\r\n .sidebar-footer-link {\r\n display: flex;\r\n align-items: center;\r\n padding: 8px 15px;\r\n color: $sidebar-text;\r\n text-decoration: none;\r\n font-size: 13px;\r\n transition: all 0.2s ease;\r\n white-space: nowrap;\r\n\r\n i {\r\n width: 20px;\r\n text-align: center;\r\n margin-right: 10px;\r\n }\r\n\r\n &:hover {\r\n background: $sidebar-hover-bg;\r\n color: $sidebar-active;\r\n }\r\n\r\n &.logout {\r\n color: $cRed;\r\n\r\n &:hover {\r\n color: #e07a66;\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n.content-wrapper {\r\n margin-left: $sidebar-width;\r\n min-height: 100vh;\r\n transition: margin-left 0.3s ease;\r\n\r\n &.expanded {\r\n margin-left: $sidebar-collapsed-width;\r\n }\r\n}\r\n\r\n.top-bar {\r\n background: #fff;\r\n border-bottom: 1px solid #e8e8e8;\r\n padding: 10px 20px;\r\n display: flex;\r\n align-items: center;\r\n\r\n .top-bar-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 15px;\r\n\r\n i {\r\n cursor: pointer;\r\n font-size: 18px;\r\n color: #4e5e6a;\r\n\r\n &:hover {\r\n color: #000;\r\n }\r\n }\r\n }\r\n}\r\n\r\n.main {\r\n padding: 25px;\r\n background: #D9DEE2;\r\n min-height: calc(100vh - 45px);\r\n}\r\n\r\n.tasks_container {\r\n display: grid;\r\n grid-template-columns: repeat(5, 1fr);\r\n gap: 20px;\r\n\r\n .column {\r\n width: 100%;\r\n\r\n h2 {\r\n display: flex;\r\n padding: 10px;\r\n background: #FFF;\r\n margin-bottom: 10px;\r\n font-size: 15px;\r\n font-weight: 300;\r\n border-radius: 3px 3px 0 0;\r\n justify-content: space-between;\r\n align-items: center;\r\n\r\n i {\r\n cursor: pointer;\r\n }\r\n }\r\n\r\n &.tasks_suspended {\r\n h2 {\r\n border-bottom: 5px solid $cRed;\r\n }\r\n }\r\n\r\n &.tasks_fvat {\r\n h2 {\r\n border-bottom: 5px solid #a900fc;\r\n }\r\n }\r\n\r\n &.tasks_new {\r\n h2 {\r\n border-bottom: 5px solid #ccc;\r\n }\r\n }\r\n\r\n &.tasks_bulk {\r\n h2 {\r\n border-bottom: 5px solid #ff8c00;\r\n }\r\n }\r\n\r\n &.tasks_to_do {\r\n h2 {\r\n border-bottom: 5px solid #2aaf47;\r\n }\r\n }\r\n\r\n &.tasks_to_review {\r\n h2 {\r\n border-bottom: 5px solid #2535c9;\r\n }\r\n }\r\n\r\n &.tasks_closed {\r\n h2 {\r\n border-bottom: 5px solid #000;\r\n }\r\n }\r\n\r\n ul {\r\n list-style-type: none;\r\n margin: 0;\r\n padding: 0;\r\n\r\n .task {\r\n margin-bottom: 5px;\r\n background: #FFF;\r\n padding: 10px;\r\n border-radius: 0;\r\n display: flex;\r\n position: relative;\r\n border-radius: 6px;\r\n flex-wrap: wrap;\r\n\r\n &.notopened {\r\n border: 2px solid $cRed;\r\n }\r\n\r\n .top {\r\n display: flex;\r\n justify-content: space-between;\r\n margin-bottom: 5px;\r\n width: 100%;\r\n\r\n ._users {\r\n display: flex;\r\n gap: 5px;\r\n flex-wrap: wrap;\r\n\r\n .user {\r\n display: flex;\r\n width: 25px;\r\n height: 25px;\r\n border-radius: 6px;\r\n justify-content: center;\r\n align-items: center;\r\n color: #FFF;\r\n font-size: 12px;\r\n }\r\n }\r\n\r\n ._timer {\r\n display: flex;\r\n gap: 5px;\r\n\r\n .recursively {\r\n color: #FFF;\r\n background: #405189;\r\n border-radius: 3px;\r\n cursor: pointer;\r\n margin-bottom: 5px;\r\n width: 25px;\r\n height: 25px;\r\n text-align: center;\r\n display: block;\r\n\r\n i {\r\n font-size: 12px;\r\n }\r\n }\r\n\r\n .task_start {\r\n display: block;\r\n background: $cGreen;\r\n color: #FFF;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n margin-bottom: 5px;\r\n width: 25px;\r\n height: 25px;\r\n text-align: center;\r\n\r\n &.hidden {\r\n display: none;\r\n }\r\n\r\n i {\r\n font-size: 12px;\r\n }\r\n }\r\n\r\n .task_end {\r\n background: $cRed;\r\n display: block;\r\n color: #FFF;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n margin-bottom: 5px;\r\n width: 25px;\r\n height: 25px;\r\n text-align: center;\r\n\r\n &.hidden {\r\n display: none;\r\n }\r\n\r\n i {\r\n font-size: 12px;\r\n }\r\n }\r\n }\r\n }\r\n\r\n .middle {\r\n width: 100%;\r\n }\r\n\r\n .name {\r\n font-size: 14px;\r\n color: #333;\r\n text-decoration: none;\r\n display: block;\r\n margin-bottom: 5px;\r\n }\r\n\r\n .bottom {\r\n display: flex;\r\n justify-content: space-between;\r\n }\r\n\r\n .client_info,\r\n .current_status {\r\n font-size: 12px;\r\n font-weight: 400;\r\n\r\n strong {\r\n font-weight: 600;\r\n }\r\n }\r\n\r\n .current_status {\r\n position: relative;\r\n cursor: pointer;\r\n\r\n .status_change {\r\n position: absolute;\r\n left: 0;\r\n top: 20px;\r\n background: #fff;\r\n padding: 15px;\r\n border: 1px solid #dfdfdf;\r\n border-radius: 3px;\r\n cursor: pointer;\r\n box-shadow: 0 0 15px rgba(0, 0, 0, 0.1);\r\n z-index: 99;\r\n display: none;\r\n\r\n select {\r\n width: 250px;\r\n padding: 10px;\r\n border: 1px solid #cdcdcd;\r\n border-radius: 3px;\r\n\r\n option {\r\n font-size: 15px;\r\n padding: 3px;\r\n }\r\n }\r\n }\r\n }\r\n\r\n .dates {\r\n margin-bottom: 5px;\r\n display: flex;\r\n justify-content: space-between;\r\n font-size: 12px;\r\n\r\n .danger {\r\n color: $cRed;\r\n font-weight: 600;\r\n }\r\n\r\n .warning {\r\n color: #ff8c00;\r\n }\r\n\r\n i {\r\n font-size: 12px;\r\n color: #C9CED4;\r\n margin-right: 5px;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n/* page header */\r\n.block-header {\r\n margin-bottom: 20px;\r\n\r\n h2 {\r\n font-size: 20px;\r\n font-weight: 400;\r\n color: $cBlack;\r\n margin: 0;\r\n padding-bottom: 12px;\r\n border-bottom: 2px solid #e2e6ec;\r\n\r\n strong {\r\n font-weight: 700;\r\n }\r\n }\r\n}\r\n\r\n/* filters bar — reusable across modules */\r\n.filters-bar {\r\n display: flex;\r\n align-items: center;\r\n gap: 10px;\r\n flex-wrap: wrap;\r\n margin-bottom: 24px;\r\n padding: 12px 16px;\r\n background: #f5f7fa;\r\n border-radius: 8px;\r\n border: 1px solid #e2e6ec;\r\n\r\n select,\r\n input[type=\"text\"],\r\n input[type=\"date\"],\r\n input[type=\"number\"] {\r\n height: 36px;\r\n min-width: 170px;\r\n padding: 0 10px;\r\n border: 1px solid #d0d5dd;\r\n border-radius: 6px;\r\n background: #fff;\r\n font-size: 13px;\r\n color: $cBlack;\r\n font-family: \"Open Sans\", sans-serif;\r\n transition: border-color 0.2s;\r\n\r\n &:focus {\r\n border-color: $cBlue;\r\n outline: none;\r\n }\r\n }\r\n\r\n .btn {\r\n height: 36px;\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 5px;\r\n padding: 0 14px;\r\n border-radius: 6px;\r\n font-size: 13px;\r\n font-weight: 500;\r\n border: none;\r\n cursor: pointer;\r\n transition: background 0.2s, box-shadow 0.2s;\r\n text-decoration: none;\r\n color: #fff;\r\n\r\n &.btn-primary {\r\n background: $cBlue;\r\n\r\n &:hover {\r\n background: #4a74d4;\r\n }\r\n }\r\n\r\n &.btn-success {\r\n background: $cGreen;\r\n\r\n &:hover {\r\n background: #077a6b;\r\n }\r\n }\r\n }\r\n}\r\n\r\n/* section title — reusable */\r\n.section-title {\r\n font-size: 14px;\r\n font-weight: 600;\r\n color: $cBlack;\r\n margin: 28px 0 12px;\r\n padding-bottom: 8px;\r\n border-bottom: 1px solid #e2e6ec;\r\n}\r\n\r\n.action_menu {\r\n display: flex;\r\n margin-bottom: 25px;\r\n gap: 20px;\r\n\r\n .btn {\r\n display: inline-flex;\r\n padding: 7px 15px;\r\n color: #FFF;\r\n text-decoration: none;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 5px;\r\n\r\n &.btn_add {\r\n background: $cGreen;\r\n\r\n &:hover {\r\n background: #4a9c3b;\r\n }\r\n }\r\n\r\n &.btn_cancel {\r\n background: $cRed;\r\n\r\n &:hover {\r\n background: #b30000;\r\n }\r\n }\r\n\r\n &.disabled {\r\n opacity: .5;\r\n }\r\n }\r\n}\r\n\r\n.form_container {\r\n background: #FFF;\r\n padding: 25px;\r\n max-width: 1300px;\r\n\r\n &.full {\r\n max-width: 100%;\r\n }\r\n\r\n .form_group {\r\n margin-bottom: 10px;\r\n display: flex;\r\n\r\n >.label {\r\n width: 300px;\r\n display: inline-flex;\r\n align-items: flex-start;\r\n justify-content: right;\r\n padding-right: 10px;\r\n }\r\n\r\n .input {\r\n width: calc(100% - 300px);\r\n }\r\n }\r\n}\r\n\r\n.fullscreen_description {\r\n position: fixed !important;\r\n top: 25px;\r\n left: 25px;\r\n right: 25px;\r\n bottom: 25px;\r\n z-index: 9999;\r\n background: white;\r\n padding: 20px;\r\n overflow: auto;\r\n border-radius: 0.25rem;\r\n box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);\r\n}\r\n\r\n.fullscreen {\r\n position: absolute;\r\n top: 10px;\r\n right: 10px;\r\n cursor: pointer;\r\n color: #FFF;\r\n background: $cRed;\r\n display: inline-flex;\r\n height: 40px;\r\n width: 40px;\r\n border-radius: 6px;\r\n align-items: center;\r\n justify-content: center;\r\n transition: all 0.3s ease;\r\n\r\n &:hover {\r\n transform: scale(1.05);\r\n text-decoration: none;\r\n }\r\n}\r\n\r\n.task_popup {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n background: rgba(0, 0, 0, 0.5);\r\n display: none;\r\n z-index: 9999;\r\n\r\n .task_details {\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n background: #FFF;\r\n padding: 25px;\r\n border-radius: 6px;\r\n max-width: 1140px;\r\n width: 100%;\r\n transition: all 0.3s ease;\r\n height: 90vh;\r\n\r\n .content {\r\n height: calc(100% - 50px);\r\n }\r\n\r\n &.open_works_time {\r\n max-width: 1540px;\r\n\r\n .content {\r\n grid-template-columns: 1fr 300px 350px;\r\n\r\n .task_work_details {\r\n display: block;\r\n }\r\n }\r\n }\r\n\r\n .title {\r\n font-size: 20px;\r\n margin-bottom: 25px;\r\n display: flex;\r\n align-items: center;\r\n gap: 10px;\r\n\r\n a {\r\n border: 1px solid $cGreen;\r\n display: inline-flex;\r\n height: 30px;\r\n width: 30px;\r\n border-radius: 6px;\r\n align-items: center;\r\n justify-content: center;\r\n\r\n &:hover {\r\n text-decoration: none;\r\n }\r\n\r\n i {\r\n color: $cGreen;\r\n }\r\n\r\n &.task-delete {\r\n border: 1px solid $cRed;\r\n\r\n i {\r\n color: $cRed;\r\n }\r\n }\r\n\r\n i {\r\n font-size: 14px;\r\n }\r\n }\r\n\r\n .task-title-edit-box {\r\n align-items: center;\r\n gap: 6px;\r\n\r\n .task-title-input {\r\n height: 30px;\r\n font-size: 14px;\r\n padding: 2px 8px;\r\n width: 300px;\r\n border: 1px solid #ccc;\r\n border-radius: 4px;\r\n }\r\n\r\n a.task-title-save,\r\n a.task-title-cancel {\r\n height: 30px;\r\n width: 30px;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n border-radius: 6px;\r\n\r\n i {\r\n font-size: 13px;\r\n }\r\n }\r\n\r\n a.task-title-save {\r\n background: $cGreen;\r\n border-color: $cGreen;\r\n\r\n i {\r\n color: #fff;\r\n }\r\n }\r\n\r\n a.task-title-cancel {\r\n background: $cRed;\r\n border-color: $cRed;\r\n\r\n i {\r\n color: #fff;\r\n }\r\n }\r\n }\r\n }\r\n\r\n .close {\r\n position: absolute;\r\n top: 10px;\r\n right: 10px;\r\n cursor: pointer;\r\n }\r\n\r\n .content {\r\n display: grid;\r\n font-size: 14px;\r\n grid-template-columns: 1fr 300px;\r\n gap: 30px;\r\n transition: all 0.3s ease;\r\n\r\n h3 {\r\n width: 100%;\r\n margin-top: 0;\r\n margin-bottom: 5px;\r\n font-weight: 500;\r\n color: #000;\r\n font-size: 17px;\r\n }\r\n\r\n .left {\r\n height: 100%;\r\n overflow: hidden;\r\n\r\n .users {\r\n display: flex;\r\n gap: 20px;\r\n\r\n .user {\r\n display: flex;\r\n gap: 10px;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n\r\n .avatar {\r\n height: 30px;\r\n width: 30px;\r\n border-radius: 6px;\r\n background: #ccc;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n color: #FFF;\r\n font-size: 12px;\r\n }\r\n }\r\n }\r\n\r\n .comments {\r\n border-radius: 3px;\r\n max-height: 406px;\r\n overflow-y: auto;\r\n\r\n .new_comment {\r\n margin-bottom: 10px;\r\n\r\n textarea {\r\n height: 75px;\r\n margin-bottom: 10px;\r\n border-radius: 6px;\r\n }\r\n\r\n .add_comment {\r\n background: $cGreen;\r\n color: #FFF;\r\n padding: 10px;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 200px;\r\n text-decoration: none;\r\n\r\n &:hover {\r\n background: #4a9c3b;\r\n }\r\n }\r\n }\r\n\r\n ul {\r\n margin: 0;\r\n padding: 0;\r\n list-style-type: none;\r\n\r\n li {\r\n background: #ced4da;\r\n margin-bottom: 5px;\r\n padding: 15px;\r\n border-radius: 6px;\r\n position: relative;\r\n\r\n .delete_comment {\r\n position: absolute;\r\n top: 10px;\r\n right: 10px;\r\n cursor: pointer;\r\n color: $cRed;\r\n }\r\n\r\n .author {\r\n font-weight: 600;\r\n margin-bottom: 5px;\r\n display: inline-flex;\r\n margin-right: 10px;\r\n }\r\n\r\n .date {\r\n font-size: 12px;\r\n margin-bottom: 5px;\r\n display: inline-flex;\r\n }\r\n\r\n .text {\r\n margin-bottom: 15px;\r\n font-size: 13px;\r\n }\r\n }\r\n }\r\n }\r\n\r\n .checklist {\r\n border-radius: 3px;\r\n margin-bottom: 10px;\r\n\r\n .new_element {\r\n display: flex;\r\n margin-bottom: 10px;\r\n\r\n input {\r\n border-radius: 6px 0 0 6px;\r\n }\r\n\r\n a {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 10px;\r\n border-radius: 0 6px 6px 0;\r\n text-decoration: none;\r\n width: 35px;\r\n background: $cGreen;\r\n color: #FFF;\r\n }\r\n }\r\n\r\n ul {\r\n margin: 0;\r\n padding: 0;\r\n list-style-type: none;\r\n overflow-y: auto;\r\n max-height: calc(90vh - 400px);\r\n\r\n li {\r\n display: flex;\r\n gap: 10px;\r\n margin-bottom: 5px;\r\n background: #FFF;\r\n border-radius: 3px;\r\n padding: 10px;\r\n border: 1px solid #cdcdcd;\r\n font-size: 13px;\r\n align-items: flex-start;\r\n\r\n a {\r\n margin-left: auto;\r\n margin-right: 0;\r\n cursor: pointer;\r\n background: $cRed;\r\n display: flex;\r\n height: 25px;\r\n width: 25px;\r\n min-width: 25px;\r\n justify-content: center;\r\n align-items: center;\r\n border: 0;\r\n border-radius: 3px;\r\n transition: all 0.3s ease;\r\n\r\n &:hover {\r\n text-decoration: none;\r\n background: #b30000;\r\n }\r\n\r\n i {\r\n color: #FFF;\r\n font-size: 12px;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n .attachments {\r\n margin-top: 10px;\r\n border: 1px solid #e6e9ed;\r\n border-radius: 8px;\r\n padding: 12px;\r\n background: #f9fbfd;\r\n\r\n h3 {\r\n margin-bottom: 10px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n }\r\n\r\n .attachments_upload {\r\n display: flex;\r\n gap: 10px;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n\r\n .attachment_file_input {\r\n flex: 1;\r\n margin-bottom: 0;\r\n border-radius: 6px;\r\n background: #fff;\r\n }\r\n\r\n .attachment-upload-btn {\r\n white-space: nowrap;\r\n border-radius: 6px;\r\n min-width: 150px;\r\n\r\n &.is-loading {\r\n pointer-events: none;\r\n opacity: 0.85;\r\n\r\n i {\r\n margin-right: 6px;\r\n }\r\n }\r\n }\r\n }\r\n\r\n .attachments_list {\r\n margin: 0;\r\n padding: 0;\r\n list-style: none;\r\n display: grid;\r\n gap: 8px;\r\n max-height: 180px;\r\n overflow-y: auto;\r\n\r\n li {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n background: #fff;\r\n border: 1px solid #e4e8ee;\r\n border-radius: 6px;\r\n padding: 8px 10px;\r\n\r\n .attachment-link {\r\n color: #1f3d72;\r\n text-decoration: none;\r\n font-weight: 600;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n max-width: calc(100% - 140px);\r\n\r\n &:hover {\r\n text-decoration: underline;\r\n }\r\n }\r\n\r\n small {\r\n color: #6b7280;\r\n margin-right: auto;\r\n }\r\n\r\n .attachment-rename,\r\n .attachment-delete {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 28px;\r\n width: 28px;\r\n border-radius: 4px;\r\n text-decoration: none;\r\n transition: all 0.2s ease;\r\n }\r\n\r\n .attachment-rename {\r\n border: 1px solid #d8e2f6;\r\n color: $cBlue;\r\n background: #f4f8ff;\r\n\r\n &:hover {\r\n background: #e7f0ff;\r\n }\r\n }\r\n\r\n .attachment-delete {\r\n border: 1px solid #f1d3d1;\r\n color: $cRed;\r\n background: #fff6f6;\r\n\r\n &:hover {\r\n background: #ffeaea;\r\n }\r\n }\r\n }\r\n\r\n .attachments-empty {\r\n color: #6b7280;\r\n border-style: dashed;\r\n justify-content: center;\r\n font-size: 13px;\r\n }\r\n }\r\n }\r\n\r\n .description {\r\n padding: 15px;\r\n border-radius: 0.25rem;\r\n border: 1px solid #cdcdcd;\r\n margin-bottom: 15px;\r\n max-height: 202px;\r\n overflow-x: hidden;\r\n position: relative;\r\n }\r\n }\r\n\r\n .right {\r\n\r\n .box {\r\n margin-bottom: 15px;\r\n }\r\n\r\n .time {\r\n a.time_worked_toggle {\r\n @extend .default-btn;\r\n color: #299cdb;\r\n display: inline-flex;\r\n border: 1px solid #299cdb;\r\n\r\n &:hover {\r\n background: #dff0fa;\r\n text-decoration: none;\r\n }\r\n\r\n &:active,\r\n &:focus {\r\n text-decoration: none;\r\n }\r\n }\r\n\r\n a:not(.time_worked_toggle) {\r\n @extend .default-btn;\r\n margin-top: 10px;\r\n text-decoration: none;\r\n gap: 10px;\r\n\r\n &.task_start {\r\n background: #0ab39c;\r\n color: #FFF;\r\n\r\n &:hover {\r\n background: #099885;\r\n }\r\n }\r\n\r\n &.task_end {\r\n background: $cRed;\r\n color: #FFF;\r\n }\r\n\r\n &.hidden {\r\n display: none;\r\n }\r\n }\r\n }\r\n\r\n .dates {\r\n display: flex;\r\n justify-content: space-between;\r\n flex-wrap: wrap;\r\n\r\n .danger {\r\n color: $cRed;\r\n font-weight: 600;\r\n }\r\n\r\n .warning {\r\n color: #ff8c00;\r\n }\r\n\r\n i {\r\n color: #C9CED4;\r\n margin-right: 5px;\r\n }\r\n }\r\n }\r\n\r\n .task_work_details {\r\n display: none;\r\n overflow-y: auto;\r\n max-height: 508px;\r\n width: 100%;\r\n padding-right: 10px;\r\n padding-top: 4px;\r\n\r\n ._line {\r\n display: flex;\r\n flex-wrap: wrap;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 5px;\r\n\r\n ._user {\r\n width: 100%;\r\n font-size: 13px;\r\n }\r\n\r\n input {\r\n width: calc(50% - 25px);\r\n text-align: center;\r\n margin-left: 2px;\r\n margin-right: 2px;\r\n }\r\n }\r\n\r\n ._work_delete {\r\n display: inline-flex;\r\n height: 35px;\r\n width: 35px;\r\n border-radius: 6px;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n border: 1px solid $cRed;\r\n margin-left: 2px;\r\n transition: all 0.3s ease;\r\n\r\n &:hover {\r\n background: $cRed;\r\n\r\n i {\r\n color: #FFF;\r\n }\r\n }\r\n\r\n i {\r\n transition: all 0.3s ease;\r\n color: $cRed;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n.table {\r\n width: 100%;\r\n border: none;\r\n border-radius: 8px;\r\n overflow: hidden;\r\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);\r\n background: #fff;\r\n\r\n th,\r\n td {\r\n padding: 10px 14px;\r\n border: none;\r\n border-bottom: 1px solid #eef0f3;\r\n text-align: left;\r\n vertical-align: middle;\r\n }\r\n\r\n thead th {\r\n background: #f5f7fa;\r\n color: #4e5e6a;\r\n font-weight: 600;\r\n font-size: 12px;\r\n text-transform: uppercase;\r\n letter-spacing: 0.3px;\r\n white-space: nowrap;\r\n border-bottom: 2px solid #e2e6ec;\r\n }\r\n\r\n tbody tr {\r\n transition: background 0.15s ease;\r\n\r\n &:last-child td {\r\n border-bottom: none;\r\n }\r\n\r\n &:hover {\r\n background: #f8fafd;\r\n }\r\n }\r\n\r\n td.center,\r\n th.center {\r\n text-align: center;\r\n }\r\n\r\n td.left,\r\n th.left {\r\n text-align: left;\r\n }\r\n\r\n td.right,\r\n th.right {\r\n text-align: right;\r\n }\r\n\r\n // empty state\r\n td[colspan] {\r\n text-align: center;\r\n color: #8896a4;\r\n padding: 24px 14px;\r\n font-style: italic;\r\n }\r\n}\r\n\r\n.projects_container {\r\n background: #FFF;\r\n padding: 15px;\r\n border-radius: 6px;\r\n display: flex;\r\n gap: 20px;\r\n\r\n .left {\r\n width: calc(100% - 250px);\r\n\r\n ._projects,\r\n ._users {\r\n display: flex;\r\n gap: 20px;\r\n flex-wrap: wrap;\r\n }\r\n }\r\n\r\n .right {\r\n width: 250px;\r\n display: flex;\r\n flex-wrap: wrap;\r\n align-items: flex-start;\r\n justify-content: center;\r\n gap: 20px;\r\n border-left: 1px solid #cdcdcd;\r\n padding-left: 15px;\r\n\r\n select {\r\n width: 200px;\r\n }\r\n }\r\n}\r\n\r\n.default_popup {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n background: rgba(0, 0, 0, 0.5);\r\n display: none;\r\n\r\n .popup_content {\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n background: #FFF;\r\n padding: 25px;\r\n border-radius: 0;\r\n max-width: 1140px;\r\n width: 100%;\r\n\r\n .close {\r\n position: absolute;\r\n top: 10px;\r\n right: 10px;\r\n cursor: pointer;\r\n }\r\n }\r\n}\r\n\r\n#fg-cron {\r\n margin: 10px 0;\r\n\r\n .countdown {\r\n background: $cGreen;\r\n color: #FFF;\r\n padding: 10px;\r\n }\r\n\r\n #cron-container {\r\n max-height: 300px;\r\n overflow-x: hidden;\r\n overflow-y: auto;\r\n\r\n .msg {\r\n font-size: 13px;\r\n padding: 5px;\r\n border-bottom: 1px solid #e8e8e8;\r\n }\r\n }\r\n}\r\n\r\n.card {\r\n background: #FFF;\r\n padding: 25px;\r\n border-radius: 6px;\r\n color: #000;\r\n font-size: 15px;\r\n max-width: 1280px;\r\n\r\n &.mb25 {\r\n margin-bottom: 25px;\r\n }\r\n\r\n .card-header {\r\n font-weight: 600;\r\n }\r\n\r\n .card-body {\r\n padding-top: 10px;\r\n\r\n table {\r\n border-collapse: collapse;\r\n\r\n th,\r\n td {\r\n font-size: 14px;\r\n\r\n &.bold {\r\n font-weight: 600;\r\n }\r\n\r\n &.text-right {\r\n text-align: right;\r\n }\r\n\r\n &.text-center {\r\n text-align: center;\r\n }\r\n\r\n .close-task {\r\n text-decoration: none;\r\n color: $cBlue;\r\n\r\n &:hover {\r\n color: $cRed;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n.finance-summary {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr 1fr 1fr;\r\n gap: 10px;\r\n\r\n .panel {\r\n background: #FFF;\r\n border-radius: 6px;\r\n padding: 15px;\r\n\r\n h1 {\r\n font-size: 20px;\r\n margin: 0;\r\n }\r\n\r\n span {\r\n font-size: 0.85em;\r\n }\r\n }\r\n}\r\n\r\n.finance-manager {\r\n display: grid;\r\n gap: 10px;\r\n grid-template-columns: 200px 1fr 500px;\r\n padding-top: 25px;\r\n\r\n .manage-menu {\r\n display: inline-block;\r\n margin-right: 10px;\r\n\r\n a {\r\n color: #333333;\r\n text-decoration: none;\r\n font-weight: 300;\r\n display: block;\r\n }\r\n }\r\n\r\n .actions {\r\n width: 100px;\r\n text-align: center;\r\n\r\n a {\r\n display: inline-flex;\r\n margin: 0 2px;\r\n height: 25px;\r\n width: 25px;\r\n align-items: center;\r\n justify-content: center;\r\n text-decoration: none;\r\n color: #000;\r\n border: 1px solid #e7e7e7;\r\n font-size: 11px;\r\n border-radius: 3px;\r\n transition: all 0.3s ease;\r\n\r\n &:hover {\r\n border: 1px solid $cBlue;\r\n }\r\n }\r\n }\r\n}\r\n\r\n.bootstrap-tagsinput {\r\n .tag {\r\n background: $cBlue;\r\n font-size: 13px;\r\n padding: 5px 10px;\r\n border-radius: 12px;\r\n\r\n [data-role=\"remove\"] {\r\n color: #FFF !important;\r\n\r\n &:hover {\r\n box-shadow: none !important;\r\n color: #000 !important\r\n }\r\n }\r\n }\r\n}\r\n\r\n.finance-tags {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 5px;\r\n\r\n a:not(.btn) {\r\n display: flex;\r\n width: 100%;\r\n text-decoration: none;\r\n color: $cBlack;\r\n\r\n &.zoom-100 {\r\n font-size: 1.2em;\r\n }\r\n\r\n &.zoom-90 {\r\n font-size: 1.15em;\r\n }\r\n\r\n &.zoom-80 {\r\n font-size: 1.1em;\r\n }\r\n\r\n &.zoom-70 {\r\n font-size: 1.05em;\r\n }\r\n\r\n &.zoom-60 {\r\n font-size: 1em;\r\n }\r\n\r\n &.zoom-50 {\r\n font-size: 0.95em;\r\n }\r\n\r\n &.zoom-40 {\r\n font-size: 0.9em;\r\n }\r\n\r\n &.zoom-30 {\r\n font-size: 0.85em;\r\n }\r\n\r\n &.zoom-20 {\r\n font-size: 0.8em;\r\n }\r\n\r\n &.zoom-10 {\r\n font-size: 0.75em;\r\n }\r\n\r\n &.zoom-0 {\r\n font-size: 0.7em;\r\n }\r\n }\r\n}\r\n\r\n.manage-menu {\r\n position: relative;\r\n\r\n .context-menu {\r\n border-left: 4px dotted #000;\r\n width: 1px;\r\n height: 100%;\r\n }\r\n\r\n .context-menu-container {\r\n position: absolute;\r\n display: none;\r\n background: #FFF;\r\n box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.1);\r\n top: 2px;\r\n left: 2px;\r\n\r\n ul {\r\n list-style-type: none;\r\n margin: 0;\r\n padding: 0;\r\n\r\n li {\r\n a {\r\n display: block;\r\n padding: 7px 15px;\r\n white-space: nowrap;\r\n\r\n &:hover {\r\n background: #f8f8f8;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n &:hover {\r\n .context-menu-container {\r\n display: block;\r\n }\r\n }\r\n}\r\n\r\n.wiki-categories {\r\n display: grid;\r\n gap: 10px;\r\n margin-top: 25px;\r\n grid-template-columns: 1fr 1fr 1fr 1fr;\r\n\r\n .category {\r\n background: #FFF;\r\n padding: 10px;\r\n\r\n .users {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr 1fr 1fr;\r\n gap: 5px;\r\n\r\n .user {\r\n display: flex;\r\n height: 25px;\r\n width: 25px;\r\n border-radius: 50%;\r\n background: #ccc;\r\n justify-content: center;\r\n align-items: center;\r\n color: #FFF;\r\n font-size: 12px;\r\n }\r\n }\r\n\r\n .actions {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n\r\n a {\r\n display: block;\r\n color: $cBlack;\r\n font-size: 13px;\r\n text-align: center;\r\n }\r\n }\r\n\r\n .title {\r\n margin-bottom: 5px;\r\n\r\n a {\r\n display: block;\r\n color: $cBlack;\r\n font-size: 13px;\r\n font-weight: 600;\r\n }\r\n }\r\n }\r\n}\r\n\r\n.bootstrap-datetimepicker-widget .picker-switch {\r\n a {\r\n display: block;\r\n color: #000;\r\n }\r\n}\r\n\r\n.gantt_users {\r\n display: flex;\r\n gap: 20px;\r\n}\r\n\r\n#g-results {\r\n background: #FFF;\r\n padding: 25px;\r\n}\r\n\r\n.g-menu-container {\r\n margin-bottom: 15px;\r\n\r\n .right-menu {\r\n display: none;\r\n }\r\n}\r\n\r\n.g-center {\r\n text-align: center;\r\n}\r\n\r\n.alert {\r\n background: $cGreen;\r\n border: 0;\r\n color: #FFF;\r\n}\r\n\r\n.tasks_main_view {\r\n display: flex;\r\n gap: 20px;\r\n\r\n ._left_column {\r\n padding: 25px;\r\n background: #fcfcfc;\r\n border-right: 1px solid #e8e8e8;\r\n width: 350px;\r\n\r\n label {\r\n font-weight: 400;\r\n font-size: 14px;\r\n }\r\n\r\n select[name=\"filtr\"] {\r\n margin-bottom: 10px;\r\n }\r\n\r\n ._buttons {\r\n display: flex;\r\n gap: 10px;\r\n justify-content: space-between;\r\n\r\n .btn {\r\n flex: 1;\r\n }\r\n }\r\n }\r\n\r\n ._right_column {\r\n flex: 1;\r\n max-width: calc(100% - 350px);\r\n }\r\n}\r\n\r\n#billing-summary {\r\n .card-header {\r\n padding: 10px;\r\n }\r\n\r\n .billing-kpi {\r\n border: 1px solid #dee2e6;\r\n border-radius: 6px;\r\n padding: 10px 12px;\r\n background: #ffffff;\r\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\r\n }\r\n\r\n .billing-kpi-label {\r\n font-size: 12px;\r\n color: #6c757d;\r\n margin-bottom: 3px;\r\n }\r\n\r\n .billing-kpi-value {\r\n font-size: 21px;\r\n font-weight: 700;\r\n line-height: 1.1;\r\n }\r\n\r\n .billing-details-row {\r\n display: none;\r\n }\r\n\r\n .billing-client-name {\r\n font-weight: 600;\r\n }\r\n\r\n .billing-table>thead>tr>th {\r\n background: #f8f9fa;\r\n }\r\n\r\n .billing-details-wrap {\r\n background: #f8fbff;\r\n }\r\n}\r\n\r\n/* sidebar submenu */\r\n\r\n/* vacations module */\r\n\r\n.vacation-type-badge {\r\n display: inline-block;\r\n padding: 2px 8px;\r\n border-radius: 4px;\r\n font-size: 12px;\r\n font-weight: 500;\r\n background: #e3f0ff;\r\n color: #2563eb;\r\n\r\n &.type-chorobowe {\r\n background: #fff3e0;\r\n color: #e65100;\r\n }\r\n\r\n &.type-inna_nieobecnosc {\r\n background: #f3e5f5;\r\n color: #7b1fa2;\r\n }\r\n}"]} \ No newline at end of file +{"version":3,"sources":["style.scss"],"names":[],"mappings":"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","file":"style.css","sourcesContent":["$cBlue: #6690F4;\r\n$cRed: #cc563d;\r\n$cGreen: #099885;\r\n$cBlack: #4e5e6a;\r\n\r\n.default-btn {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 40px;\r\n border-radius: 6px;\r\n padding: 0 15px;\r\n transition: all .3s ease;\r\n\r\n &:hover {\r\n text-decoration: none;\r\n }\r\n}\r\n\r\n.animate {\r\n animation: mymove 3s infinite;\r\n}\r\n\r\n.text-right {\r\n text-align: right;\r\n}\r\n\r\n.nowrap {\r\n white-space: nowrap;\r\n}\r\n\r\ntable {\r\n border-collapse: collapse;\r\n font-size: 13px;\r\n}\r\n\r\nsmall {\r\n font-size: .75em;\r\n}\r\n\r\n@keyframes mymove {\r\n 50% {\r\n opacity: .33;\r\n }\r\n}\r\n\r\n/* motion */\r\n@keyframes gradient-animation {\r\n 0% {\r\n background-position: 15% 0%;\r\n }\r\n\r\n 50% {\r\n background-position: 85% 100%;\r\n }\r\n\r\n 100% {\r\n background-position: 15% 0%;\r\n }\r\n}\r\n\r\n@keyframes frame-enter {\r\n 0% {\r\n clip-path: polygon(0% 100%, 3px 100%, 3px 3px, calc(100% - 3px) 3px, calc(100% - 3px) calc(100% - 3px), 3px calc(100% - 3px), 3px 100%, 100% 100%, 100% 0%, 0% 0%);\r\n }\r\n\r\n 25% {\r\n clip-path: polygon(0% 100%, 3px 100%, 3px 3px, calc(100% - 3px) 3px, calc(100% - 3px) calc(100% - 3px), calc(100% - 3px) calc(100% - 3px), calc(100% - 3px) 100%, 100% 100%, 100% 0%, 0% 0%);\r\n }\r\n\r\n 50% {\r\n clip-path: polygon(0% 100%, 3px 100%, 3px 3px, calc(100% - 3px) 3px, calc(100% - 3px) 3px, calc(100% - 3px) 3px, calc(100% - 3px) 3px, calc(100% - 3px) 3px, 100% 0%, 0% 0%);\r\n }\r\n\r\n 75% {\r\n -webkit-clip-path: polygon(0% 100%, 3px 100%, 3px 3px, 3px 3px, 3px 3px, 3px 3px, 3px 3px, 3px 3px, 3px 0%, 0% 0%);\r\n }\r\n\r\n 100% {\r\n -webkit-clip-path: polygon(0% 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 3px 100%, 0% 100%);\r\n }\r\n}\r\n\r\n* {\r\n box-sizing: border-box;\r\n}\r\n\r\nbody {\r\n font-family: \"Open Sans\", sans-serif;\r\n margin: 0;\r\n padding: 0;\r\n font-size: 15px;\r\n color: #4e5e6a;\r\n}\r\n\r\n.btn {\r\n padding: 9px 25px;\r\n transition: all 0.3s ease;\r\n color: #FFF;\r\n border: 0;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n display: inline-flex;\r\n text-decoration: none;\r\n gap: 5px;\r\n justify-content: center;\r\n align-items: center;\r\n\r\n &.btn_small,\r\n &.btn-xs,\r\n &.btn-sm {\r\n padding: 5px 7px;\r\n font-size: 13px;\r\n\r\n i {\r\n font-size: 12px;\r\n }\r\n }\r\n\r\n &.btn-success {\r\n background: $cGreen;\r\n\r\n &:hover {\r\n background: #4a9c3b;\r\n }\r\n }\r\n\r\n &.btn-primary {\r\n background: $cBlue;\r\n\r\n &:hover {\r\n background: #3164db;\r\n }\r\n }\r\n\r\n &.btn-danger {\r\n background: $cRed;\r\n\r\n &:hover {\r\n background: #b30000;\r\n }\r\n }\r\n}\r\n\r\n.hide {\r\n display: none;\r\n}\r\n\r\n.form-error {\r\n color: $cRed;\r\n font-size: 13px;\r\n}\r\n\r\n.input-group {\r\n margin-bottom: 10px;\r\n}\r\n\r\n.form-field {\r\n margin-bottom: 15px;\r\n\r\n label {\r\n display: block;\r\n font-size: 13px;\r\n font-weight: 600;\r\n margin-bottom: 4px;\r\n color: #4e5e6a;\r\n }\r\n}\r\n\r\n.password-wrap {\r\n position: relative;\r\n\r\n .form-control {\r\n padding-right: 40px;\r\n }\r\n\r\n .password-eye {\r\n position: absolute;\r\n right: 10px;\r\n top: 50%;\r\n transform: translateY(-50%);\r\n color: #999;\r\n text-decoration: none;\r\n z-index: 2;\r\n\r\n &:hover {\r\n color: #333;\r\n }\r\n }\r\n}\r\n\r\ninput[type=\"checkbox\"] {\r\n border: 1px solid #cdcdcd;\r\n}\r\n\r\n.form-control {\r\n border: 1px solid #cdcdcd;\r\n border-radius: 6px;\r\n height: 35px;\r\n width: 100%;\r\n padding: 5px;\r\n font-family: \"Open Sans\", sans-serif;\r\n\r\n option {\r\n padding: 5px;\r\n }\r\n\r\n &:focus {\r\n border: 1px solid $cBlue;\r\n outline: none;\r\n }\r\n}\r\n\r\n.unlogged {\r\n background: #EEF1F9;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 100vh;\r\n\r\n .box-login {\r\n background: #FFF;\r\n padding: 25px;\r\n border-radius: 6px;\r\n width: 400px;\r\n\r\n .title {\r\n text-align: center;\r\n padding: 10px 10px 25px;\r\n border-bottom: 1px solid #cdcdcd;\r\n font-size: 20px;\r\n margin-bottom: 25px;\r\n }\r\n }\r\n}\r\n\r\n$sidebar-width: 220px;\r\n$sidebar-collapsed-width: 60px;\r\n$sidebar-bg: #1e2a3a;\r\n$sidebar-text: #c2c7d0;\r\n$sidebar-active: #fff;\r\n$sidebar-hover-bg: rgba(255, 255, 255, 0.08);\r\n\r\n.sidebar {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n width: $sidebar-width;\r\n height: 100vh;\r\n background: $sidebar-bg;\r\n display: flex;\r\n flex-direction: column;\r\n z-index: 1000;\r\n transition: width 0.3s ease;\r\n overflow: hidden;\r\n\r\n &.collapsed {\r\n width: $sidebar-collapsed-width;\r\n\r\n .sidebar-header .sidebar-logo span,\r\n .sidebar-nav ul li a span,\r\n .sidebar-footer span,\r\n .sidebar-footer .sidebar-user span {\r\n display: none;\r\n }\r\n\r\n .sidebar-header .sidebar-logo {\r\n font-size: 0;\r\n\r\n &::first-letter {\r\n font-size: 16px;\r\n }\r\n }\r\n\r\n .sidebar-nav ul li a {\r\n justify-content: center;\r\n padding: 10px;\r\n\r\n i {\r\n margin-right: 0;\r\n }\r\n }\r\n\r\n .sidebar-nav ul li.has-submenu {\r\n .submenu-arrow {\r\n display: none;\r\n }\r\n\r\n .sidebar-submenu {\r\n display: none;\r\n }\r\n }\r\n\r\n .sidebar-footer .sidebar-footer-link,\r\n .sidebar-footer .sidebar-user {\r\n justify-content: center;\r\n padding: 8px 10px;\r\n\r\n i {\r\n margin-right: 0;\r\n }\r\n }\r\n }\r\n\r\n .sidebar-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 15px;\r\n border-bottom: 1px solid rgba(255, 255, 255, 0.1);\r\n\r\n .sidebar-logo {\r\n color: $cBlue;\r\n text-decoration: none;\r\n font-size: 16px;\r\n white-space: nowrap;\r\n\r\n span {\r\n font-weight: 700;\r\n }\r\n }\r\n\r\n .sidebar-toggle {\r\n cursor: pointer;\r\n color: $sidebar-text;\r\n font-size: 16px;\r\n transition: color 0.2s ease;\r\n\r\n &:hover {\r\n color: #fff;\r\n }\r\n }\r\n }\r\n\r\n .sidebar-nav {\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 10px 0;\r\n\r\n ul {\r\n list-style: none;\r\n margin: 0;\r\n padding: 0;\r\n\r\n li {\r\n a {\r\n display: flex;\r\n align-items: center;\r\n padding: 10px 15px;\r\n color: $sidebar-text;\r\n text-decoration: none;\r\n font-size: 14px;\r\n transition: all 0.2s ease;\r\n white-space: nowrap;\r\n\r\n i {\r\n width: 20px;\r\n text-align: center;\r\n margin-right: 10px;\r\n font-size: 15px;\r\n }\r\n\r\n &:hover {\r\n background: $sidebar-hover-bg;\r\n color: $sidebar-active;\r\n }\r\n }\r\n\r\n &.active a {\r\n background: $sidebar-hover-bg;\r\n color: $sidebar-active;\r\n font-weight: 600;\r\n }\r\n\r\n &.has-submenu {\r\n >a .submenu-arrow {\r\n margin-left: auto;\r\n font-size: 12px;\r\n transition: transform 0.2s ease;\r\n width: auto;\r\n }\r\n\r\n &.open>a .submenu-arrow {\r\n transform: rotate(180deg);\r\n }\r\n\r\n .sidebar-submenu {\r\n max-height: 0;\r\n overflow: hidden;\r\n transition: max-height 0.25s ease;\r\n background: rgba(0, 0, 0, 0.15);\r\n\r\n li a {\r\n padding: 8px 15px 8px 45px;\r\n font-size: 13px;\r\n\r\n i {\r\n font-size: 13px;\r\n width: 16px;\r\n }\r\n }\r\n }\r\n\r\n &.open .sidebar-submenu {\r\n max-height: 200px;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n .sidebar-footer {\r\n border-top: 1px solid rgba(255, 255, 255, 0.1);\r\n padding: 10px 0;\r\n\r\n .sidebar-user {\r\n display: flex;\r\n align-items: center;\r\n padding: 8px 15px;\r\n color: $sidebar-text;\r\n font-size: 13px;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n\r\n i {\r\n margin-right: 10px;\r\n color: $cBlue;\r\n }\r\n }\r\n\r\n .sidebar-footer-link {\r\n display: flex;\r\n align-items: center;\r\n padding: 8px 15px;\r\n color: $sidebar-text;\r\n text-decoration: none;\r\n font-size: 13px;\r\n transition: all 0.2s ease;\r\n white-space: nowrap;\r\n\r\n i {\r\n width: 20px;\r\n text-align: center;\r\n margin-right: 10px;\r\n }\r\n\r\n &:hover {\r\n background: $sidebar-hover-bg;\r\n color: $sidebar-active;\r\n }\r\n\r\n &.logout {\r\n color: $cRed;\r\n\r\n &:hover {\r\n color: #e07a66;\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n.content-wrapper {\r\n margin-left: $sidebar-width;\r\n min-height: 100vh;\r\n transition: margin-left 0.3s ease;\r\n\r\n &.expanded {\r\n margin-left: $sidebar-collapsed-width;\r\n }\r\n}\r\n\r\n.top-bar {\r\n background: #fff;\r\n border-bottom: 1px solid #e8e8e8;\r\n padding: 10px 20px;\r\n display: flex;\r\n align-items: center;\r\n\r\n .top-bar-left {\r\n display: flex;\r\n align-items: center;\r\n gap: 15px;\r\n\r\n i {\r\n cursor: pointer;\r\n font-size: 18px;\r\n color: #4e5e6a;\r\n\r\n &:hover {\r\n color: #000;\r\n }\r\n }\r\n }\r\n}\r\n\r\n.main {\r\n padding: 25px;\r\n background: #D9DEE2;\r\n min-height: calc(100vh - 45px);\r\n}\r\n\r\n.tasks_container {\r\n display: grid;\r\n grid-template-columns: repeat(5, 1fr);\r\n gap: 20px;\r\n\r\n .column {\r\n width: 100%;\r\n\r\n h2 {\r\n display: flex;\r\n padding: 10px;\r\n background: #FFF;\r\n margin-bottom: 10px;\r\n font-size: 15px;\r\n font-weight: 300;\r\n border-radius: 3px 3px 0 0;\r\n justify-content: space-between;\r\n align-items: center;\r\n\r\n i {\r\n cursor: pointer;\r\n }\r\n }\r\n\r\n &.tasks_suspended {\r\n h2 {\r\n border-bottom: 5px solid $cRed;\r\n }\r\n }\r\n\r\n &.tasks_fvat {\r\n h2 {\r\n border-bottom: 5px solid #a900fc;\r\n }\r\n }\r\n\r\n &.tasks_new {\r\n h2 {\r\n border-bottom: 5px solid #ccc;\r\n }\r\n }\r\n\r\n &.tasks_bulk {\r\n h2 {\r\n border-bottom: 5px solid #ff8c00;\r\n }\r\n }\r\n\r\n &.tasks_to_do {\r\n h2 {\r\n border-bottom: 5px solid #2aaf47;\r\n }\r\n }\r\n\r\n &.tasks_to_review {\r\n h2 {\r\n border-bottom: 5px solid #2535c9;\r\n }\r\n }\r\n\r\n &.tasks_closed {\r\n h2 {\r\n border-bottom: 5px solid #000;\r\n }\r\n }\r\n\r\n ul {\r\n list-style-type: none;\r\n margin: 0;\r\n padding: 0;\r\n\r\n .task {\r\n margin-bottom: 5px;\r\n background: #FFF;\r\n padding: 10px;\r\n border-radius: 0;\r\n display: flex;\r\n position: relative;\r\n border-radius: 6px;\r\n flex-wrap: wrap;\r\n\r\n &.notopened {\r\n border: 2px solid $cRed;\r\n }\r\n\r\n .top {\r\n display: flex;\r\n justify-content: space-between;\r\n margin-bottom: 5px;\r\n width: 100%;\r\n\r\n ._users {\r\n display: flex;\r\n gap: 5px;\r\n flex-wrap: wrap;\r\n\r\n .user {\r\n display: flex;\r\n width: 25px;\r\n height: 25px;\r\n border-radius: 6px;\r\n justify-content: center;\r\n align-items: center;\r\n color: #FFF;\r\n font-size: 12px;\r\n }\r\n }\r\n\r\n ._timer {\r\n display: flex;\r\n gap: 5px;\r\n\r\n .recursively {\r\n color: #FFF;\r\n background: #405189;\r\n border-radius: 3px;\r\n cursor: pointer;\r\n margin-bottom: 5px;\r\n width: 25px;\r\n height: 25px;\r\n text-align: center;\r\n display: block;\r\n\r\n i {\r\n font-size: 12px;\r\n }\r\n }\r\n\r\n .task_start {\r\n display: block;\r\n background: $cGreen;\r\n color: #FFF;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n margin-bottom: 5px;\r\n width: 25px;\r\n height: 25px;\r\n text-align: center;\r\n\r\n &.hidden {\r\n display: none;\r\n }\r\n\r\n i {\r\n font-size: 12px;\r\n }\r\n }\r\n\r\n .task_end {\r\n background: $cRed;\r\n display: block;\r\n color: #FFF;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n margin-bottom: 5px;\r\n width: 25px;\r\n height: 25px;\r\n text-align: center;\r\n\r\n &.hidden {\r\n display: none;\r\n }\r\n\r\n i {\r\n font-size: 12px;\r\n }\r\n }\r\n }\r\n }\r\n\r\n .middle {\r\n width: 100%;\r\n }\r\n\r\n .name {\r\n font-size: 14px;\r\n color: #333;\r\n text-decoration: none;\r\n display: block;\r\n margin-bottom: 5px;\r\n }\r\n\r\n .bottom {\r\n display: flex;\r\n justify-content: space-between;\r\n }\r\n\r\n .client_info,\r\n .current_status {\r\n font-size: 12px;\r\n font-weight: 400;\r\n\r\n strong {\r\n font-weight: 600;\r\n }\r\n }\r\n\r\n .current_status {\r\n position: relative;\r\n cursor: pointer;\r\n\r\n .status_change {\r\n position: absolute;\r\n left: 0;\r\n top: 20px;\r\n background: #fff;\r\n padding: 15px;\r\n border: 1px solid #dfdfdf;\r\n border-radius: 3px;\r\n cursor: pointer;\r\n box-shadow: 0 0 15px rgba(0, 0, 0, 0.1);\r\n z-index: 99;\r\n display: none;\r\n\r\n select {\r\n width: 250px;\r\n padding: 10px;\r\n border: 1px solid #cdcdcd;\r\n border-radius: 3px;\r\n\r\n option {\r\n font-size: 15px;\r\n padding: 3px;\r\n }\r\n }\r\n }\r\n }\r\n\r\n .dates {\r\n margin-bottom: 5px;\r\n display: flex;\r\n justify-content: space-between;\r\n font-size: 12px;\r\n\r\n .danger {\r\n color: $cRed;\r\n font-weight: 600;\r\n }\r\n\r\n .warning {\r\n color: #ff8c00;\r\n }\r\n\r\n i {\r\n font-size: 12px;\r\n color: #C9CED4;\r\n margin-right: 5px;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n/* page header */\r\n.block-header {\r\n margin-bottom: 20px;\r\n\r\n h2 {\r\n font-size: 20px;\r\n font-weight: 400;\r\n color: $cBlack;\r\n margin: 0;\r\n padding-bottom: 12px;\r\n border-bottom: 2px solid #e2e6ec;\r\n\r\n strong {\r\n font-weight: 700;\r\n }\r\n }\r\n}\r\n\r\n/* filters bar — reusable across modules */\r\n.filters-bar {\r\n display: flex;\r\n align-items: center;\r\n gap: 10px;\r\n flex-wrap: wrap;\r\n margin-bottom: 24px;\r\n padding: 12px 16px;\r\n background: #f5f7fa;\r\n border-radius: 8px;\r\n border: 1px solid #e2e6ec;\r\n\r\n select,\r\n input[type=\"text\"],\r\n input[type=\"date\"],\r\n input[type=\"number\"] {\r\n height: 36px;\r\n min-width: 170px;\r\n padding: 0 10px;\r\n border: 1px solid #d0d5dd;\r\n border-radius: 6px;\r\n background: #fff;\r\n font-size: 13px;\r\n color: $cBlack;\r\n font-family: \"Open Sans\", sans-serif;\r\n transition: border-color 0.2s;\r\n\r\n &:focus {\r\n border-color: $cBlue;\r\n outline: none;\r\n }\r\n }\r\n\r\n .btn {\r\n height: 36px;\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 5px;\r\n padding: 0 14px;\r\n border-radius: 6px;\r\n font-size: 13px;\r\n font-weight: 500;\r\n border: none;\r\n cursor: pointer;\r\n transition: background 0.2s, box-shadow 0.2s;\r\n text-decoration: none;\r\n color: #fff;\r\n\r\n &.btn-primary {\r\n background: $cBlue;\r\n\r\n &:hover {\r\n background: #4a74d4;\r\n }\r\n }\r\n\r\n &.btn-success {\r\n background: $cGreen;\r\n\r\n &:hover {\r\n background: #077a6b;\r\n }\r\n }\r\n }\r\n}\r\n\r\n/* section title — reusable */\r\n.section-title {\r\n font-size: 14px;\r\n font-weight: 600;\r\n color: $cBlack;\r\n margin: 28px 0 12px;\r\n padding-bottom: 8px;\r\n border-bottom: 1px solid #e2e6ec;\r\n}\r\n\r\n.action_menu {\r\n display: flex;\r\n margin-bottom: 25px;\r\n gap: 20px;\r\n\r\n .btn {\r\n display: inline-flex;\r\n padding: 7px 15px;\r\n color: #FFF;\r\n text-decoration: none;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 5px;\r\n\r\n &.btn_add {\r\n background: $cGreen;\r\n\r\n &:hover {\r\n background: #4a9c3b;\r\n }\r\n }\r\n\r\n &.btn_cancel {\r\n background: $cRed;\r\n\r\n &:hover {\r\n background: #b30000;\r\n }\r\n }\r\n\r\n &.disabled {\r\n opacity: .5;\r\n }\r\n }\r\n}\r\n\r\n.form_container {\r\n background: #FFF;\r\n padding: 25px;\r\n max-width: 1300px;\r\n\r\n &.full {\r\n max-width: 100%;\r\n }\r\n\r\n .form_group {\r\n margin-bottom: 10px;\r\n display: flex;\r\n\r\n >.label {\r\n width: 300px;\r\n display: inline-flex;\r\n align-items: flex-start;\r\n justify-content: right;\r\n padding-right: 10px;\r\n }\r\n\r\n .input {\r\n width: calc(100% - 300px);\r\n }\r\n }\r\n}\r\n\r\n.fullscreen_description {\r\n position: fixed !important;\r\n top: 25px;\r\n left: 25px;\r\n right: 25px;\r\n bottom: 25px;\r\n z-index: 9999;\r\n background: white;\r\n padding: 20px;\r\n overflow: auto;\r\n border-radius: 0.25rem;\r\n box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);\r\n}\r\n\r\n.fullscreen {\r\n position: absolute;\r\n top: 10px;\r\n right: 10px;\r\n cursor: pointer;\r\n color: #FFF;\r\n background: $cRed;\r\n display: inline-flex;\r\n height: 40px;\r\n width: 40px;\r\n border-radius: 6px;\r\n align-items: center;\r\n justify-content: center;\r\n transition: all 0.3s ease;\r\n\r\n &:hover {\r\n transform: scale(1.05);\r\n text-decoration: none;\r\n }\r\n}\r\n\r\n.task_popup {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n background: rgba(0, 0, 0, 0.5);\r\n display: none;\r\n z-index: 9999;\r\n\r\n .task_details {\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n background: #FFF;\r\n padding: 25px;\r\n border-radius: 6px;\r\n max-width: 1140px;\r\n width: 100%;\r\n transition: all 0.3s ease;\r\n height: 90vh;\r\n\r\n .content {\r\n height: calc(100% - 50px);\r\n }\r\n\r\n &.open_works_time {\r\n max-width: 1540px;\r\n\r\n .content {\r\n grid-template-columns: 1fr 300px 350px;\r\n\r\n .task_work_details {\r\n display: block;\r\n }\r\n }\r\n }\r\n\r\n .title {\r\n font-size: 20px;\r\n margin-bottom: 25px;\r\n display: flex;\r\n align-items: center;\r\n gap: 10px;\r\n\r\n a {\r\n border: 1px solid $cGreen;\r\n display: inline-flex;\r\n height: 30px;\r\n width: 30px;\r\n border-radius: 6px;\r\n align-items: center;\r\n justify-content: center;\r\n\r\n &:hover {\r\n text-decoration: none;\r\n }\r\n\r\n i {\r\n color: $cGreen;\r\n }\r\n\r\n &.task-delete {\r\n border: 1px solid $cRed;\r\n\r\n i {\r\n color: $cRed;\r\n }\r\n }\r\n\r\n i {\r\n font-size: 14px;\r\n }\r\n }\r\n\r\n .task-title-edit-box {\r\n align-items: center;\r\n gap: 6px;\r\n\r\n .task-title-input {\r\n height: 30px;\r\n font-size: 14px;\r\n padding: 2px 8px;\r\n width: 300px;\r\n border: 1px solid #ccc;\r\n border-radius: 4px;\r\n }\r\n\r\n a.task-title-save,\r\n a.task-title-cancel {\r\n height: 30px;\r\n width: 30px;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n border-radius: 6px;\r\n\r\n i {\r\n font-size: 13px;\r\n }\r\n }\r\n\r\n a.task-title-save {\r\n background: $cGreen;\r\n border-color: $cGreen;\r\n\r\n i {\r\n color: #fff;\r\n }\r\n }\r\n\r\n a.task-title-cancel {\r\n background: $cRed;\r\n border-color: $cRed;\r\n\r\n i {\r\n color: #fff;\r\n }\r\n }\r\n }\r\n }\r\n\r\n .close {\r\n position: absolute;\r\n top: 10px;\r\n right: 10px;\r\n cursor: pointer;\r\n }\r\n\r\n .content {\r\n display: grid;\r\n font-size: 14px;\r\n grid-template-columns: 1fr 300px;\r\n gap: 30px;\r\n transition: all 0.3s ease;\r\n\r\n h3 {\r\n width: 100%;\r\n margin-top: 0;\r\n margin-bottom: 5px;\r\n font-weight: 500;\r\n color: #000;\r\n font-size: 17px;\r\n }\r\n\r\n .left {\r\n height: 100%;\r\n overflow: hidden;\r\n\r\n .users {\r\n display: flex;\r\n gap: 20px;\r\n\r\n .user {\r\n display: flex;\r\n gap: 10px;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n\r\n .avatar {\r\n height: 30px;\r\n width: 30px;\r\n border-radius: 6px;\r\n background: #ccc;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n color: #FFF;\r\n font-size: 12px;\r\n }\r\n }\r\n }\r\n\r\n .comments {\r\n border-radius: 3px;\r\n max-height: 406px;\r\n overflow-y: auto;\r\n\r\n .new_comment {\r\n margin-bottom: 10px;\r\n\r\n textarea {\r\n height: 75px;\r\n margin-bottom: 10px;\r\n border-radius: 6px;\r\n }\r\n\r\n .add_comment {\r\n background: $cGreen;\r\n color: #FFF;\r\n padding: 10px;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 200px;\r\n text-decoration: none;\r\n\r\n &:hover {\r\n background: #4a9c3b;\r\n }\r\n }\r\n }\r\n\r\n ul {\r\n margin: 0;\r\n padding: 0;\r\n list-style-type: none;\r\n\r\n li {\r\n background: #ced4da;\r\n margin-bottom: 5px;\r\n padding: 15px;\r\n border-radius: 6px;\r\n position: relative;\r\n\r\n .delete_comment {\r\n position: absolute;\r\n top: 10px;\r\n right: 10px;\r\n cursor: pointer;\r\n color: $cRed;\r\n }\r\n\r\n .author {\r\n font-weight: 600;\r\n margin-bottom: 5px;\r\n display: inline-flex;\r\n margin-right: 10px;\r\n }\r\n\r\n .date {\r\n font-size: 12px;\r\n margin-bottom: 5px;\r\n display: inline-flex;\r\n }\r\n\r\n .text {\r\n margin-bottom: 15px;\r\n font-size: 13px;\r\n }\r\n }\r\n }\r\n }\r\n\r\n .checklist {\r\n border-radius: 3px;\r\n margin-bottom: 10px;\r\n\r\n .new_element {\r\n display: flex;\r\n margin-bottom: 10px;\r\n\r\n input {\r\n border-radius: 6px 0 0 6px;\r\n }\r\n\r\n a {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 10px;\r\n border-radius: 0 6px 6px 0;\r\n text-decoration: none;\r\n width: 35px;\r\n background: $cGreen;\r\n color: #FFF;\r\n }\r\n }\r\n\r\n ul {\r\n margin: 0;\r\n padding: 0;\r\n list-style-type: none;\r\n overflow-y: auto;\r\n max-height: calc(90vh - 400px);\r\n\r\n li {\r\n display: flex;\r\n gap: 10px;\r\n margin-bottom: 5px;\r\n background: #FFF;\r\n border-radius: 3px;\r\n padding: 10px;\r\n border: 1px solid #cdcdcd;\r\n font-size: 13px;\r\n align-items: flex-start;\r\n\r\n a {\r\n margin-left: auto;\r\n margin-right: 0;\r\n cursor: pointer;\r\n background: $cRed;\r\n display: flex;\r\n height: 25px;\r\n width: 25px;\r\n min-width: 25px;\r\n justify-content: center;\r\n align-items: center;\r\n border: 0;\r\n border-radius: 3px;\r\n transition: all 0.3s ease;\r\n\r\n &:hover {\r\n text-decoration: none;\r\n background: #b30000;\r\n }\r\n\r\n i {\r\n color: #FFF;\r\n font-size: 12px;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n .attachments {\r\n margin-top: 10px;\r\n border: 1px solid #e6e9ed;\r\n border-radius: 8px;\r\n padding: 12px;\r\n background: #f9fbfd;\r\n\r\n h3 {\r\n margin-bottom: 10px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n }\r\n\r\n .attachments_upload {\r\n display: flex;\r\n gap: 10px;\r\n align-items: center;\r\n margin-bottom: 10px;\r\n\r\n .attachment_file_input {\r\n flex: 1;\r\n margin-bottom: 0;\r\n border-radius: 6px;\r\n background: #fff;\r\n }\r\n\r\n .attachment-upload-btn {\r\n white-space: nowrap;\r\n border-radius: 6px;\r\n min-width: 150px;\r\n\r\n &.is-loading {\r\n pointer-events: none;\r\n opacity: 0.85;\r\n\r\n i {\r\n margin-right: 6px;\r\n }\r\n }\r\n }\r\n }\r\n\r\n .attachments_list {\r\n margin: 0;\r\n padding: 0;\r\n list-style: none;\r\n display: grid;\r\n gap: 8px;\r\n max-height: 180px;\r\n overflow-y: auto;\r\n\r\n li {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n background: #fff;\r\n border: 1px solid #e4e8ee;\r\n border-radius: 6px;\r\n padding: 8px 10px;\r\n\r\n .attachment-link {\r\n color: #1f3d72;\r\n text-decoration: none;\r\n font-weight: 600;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n max-width: calc(100% - 140px);\r\n\r\n &:hover {\r\n text-decoration: underline;\r\n }\r\n }\r\n\r\n small {\r\n color: #6b7280;\r\n margin-right: auto;\r\n }\r\n\r\n .attachment-rename,\r\n .attachment-delete {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 28px;\r\n width: 28px;\r\n border-radius: 4px;\r\n text-decoration: none;\r\n transition: all 0.2s ease;\r\n }\r\n\r\n .attachment-rename {\r\n border: 1px solid #d8e2f6;\r\n color: $cBlue;\r\n background: #f4f8ff;\r\n\r\n &:hover {\r\n background: #e7f0ff;\r\n }\r\n }\r\n\r\n .attachment-delete {\r\n border: 1px solid #f1d3d1;\r\n color: $cRed;\r\n background: #fff6f6;\r\n\r\n &:hover {\r\n background: #ffeaea;\r\n }\r\n }\r\n }\r\n\r\n .attachments-empty {\r\n color: #6b7280;\r\n border-style: dashed;\r\n justify-content: center;\r\n font-size: 13px;\r\n }\r\n }\r\n }\r\n\r\n .description {\r\n padding: 15px;\r\n border-radius: 0.25rem;\r\n border: 1px solid #cdcdcd;\r\n margin-bottom: 15px;\r\n max-height: 202px;\r\n overflow-x: hidden;\r\n position: relative;\r\n }\r\n }\r\n\r\n .right {\r\n\r\n .box {\r\n margin-bottom: 15px;\r\n }\r\n\r\n .time {\r\n a.time_worked_toggle {\r\n @extend .default-btn;\r\n color: #299cdb;\r\n display: inline-flex;\r\n border: 1px solid #299cdb;\r\n\r\n &:hover {\r\n background: #dff0fa;\r\n text-decoration: none;\r\n }\r\n\r\n &:active,\r\n &:focus {\r\n text-decoration: none;\r\n }\r\n }\r\n\r\n a:not(.time_worked_toggle) {\r\n @extend .default-btn;\r\n margin-top: 10px;\r\n text-decoration: none;\r\n gap: 10px;\r\n\r\n &.task_start {\r\n background: #0ab39c;\r\n color: #FFF;\r\n\r\n &:hover {\r\n background: #099885;\r\n }\r\n }\r\n\r\n &.task_end {\r\n background: $cRed;\r\n color: #FFF;\r\n }\r\n\r\n &.hidden {\r\n display: none;\r\n }\r\n }\r\n }\r\n\r\n .dates {\r\n display: flex;\r\n justify-content: space-between;\r\n flex-wrap: wrap;\r\n\r\n .danger {\r\n color: $cRed;\r\n font-weight: 600;\r\n }\r\n\r\n .warning {\r\n color: #ff8c00;\r\n }\r\n\r\n i {\r\n color: #C9CED4;\r\n margin-right: 5px;\r\n }\r\n }\r\n }\r\n\r\n .task_work_details {\r\n display: none;\r\n overflow-y: auto;\r\n max-height: 508px;\r\n width: 100%;\r\n padding-right: 10px;\r\n padding-top: 4px;\r\n\r\n ._line {\r\n display: flex;\r\n flex-wrap: wrap;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 5px;\r\n\r\n ._user {\r\n width: 100%;\r\n font-size: 13px;\r\n }\r\n\r\n input {\r\n width: calc(50% - 25px);\r\n text-align: center;\r\n margin-left: 2px;\r\n margin-right: 2px;\r\n }\r\n }\r\n\r\n ._work_delete {\r\n display: inline-flex;\r\n height: 35px;\r\n width: 35px;\r\n border-radius: 6px;\r\n align-items: center;\r\n justify-content: center;\r\n cursor: pointer;\r\n border: 1px solid $cRed;\r\n margin-left: 2px;\r\n transition: all 0.3s ease;\r\n\r\n &:hover {\r\n background: $cRed;\r\n\r\n i {\r\n color: #FFF;\r\n }\r\n }\r\n\r\n i {\r\n transition: all 0.3s ease;\r\n color: $cRed;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n.table {\r\n width: 100%;\r\n border: none;\r\n border-radius: 8px;\r\n overflow: hidden;\r\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);\r\n background: #fff;\r\n\r\n th,\r\n td {\r\n padding: 10px 14px;\r\n border: none;\r\n border-bottom: 1px solid #eef0f3;\r\n text-align: left;\r\n vertical-align: middle;\r\n }\r\n\r\n thead th {\r\n background: #f5f7fa;\r\n color: #4e5e6a;\r\n font-weight: 600;\r\n font-size: 12px;\r\n text-transform: uppercase;\r\n letter-spacing: 0.3px;\r\n white-space: nowrap;\r\n border-bottom: 2px solid #e2e6ec;\r\n }\r\n\r\n tbody tr {\r\n transition: background 0.15s ease;\r\n\r\n &:last-child td {\r\n border-bottom: none;\r\n }\r\n\r\n &:hover {\r\n background: #f8fafd;\r\n }\r\n }\r\n\r\n td.center,\r\n th.center {\r\n text-align: center;\r\n }\r\n\r\n td.left,\r\n th.left {\r\n text-align: left;\r\n }\r\n\r\n td.right,\r\n th.right {\r\n text-align: right;\r\n }\r\n\r\n // empty state\r\n td[colspan] {\r\n text-align: center;\r\n color: #8896a4;\r\n padding: 24px 14px;\r\n font-style: italic;\r\n }\r\n}\r\n\r\n.projects_container {\r\n background: #FFF;\r\n padding: 15px;\r\n border-radius: 6px;\r\n display: flex;\r\n gap: 20px;\r\n\r\n .left {\r\n width: calc(100% - 250px);\r\n\r\n ._projects,\r\n ._users {\r\n display: flex;\r\n gap: 20px;\r\n flex-wrap: wrap;\r\n }\r\n }\r\n\r\n .right {\r\n width: 250px;\r\n display: flex;\r\n flex-wrap: wrap;\r\n align-items: flex-start;\r\n justify-content: center;\r\n gap: 20px;\r\n border-left: 1px solid #cdcdcd;\r\n padding-left: 15px;\r\n\r\n select {\r\n width: 200px;\r\n }\r\n }\r\n}\r\n\r\n.default_popup {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n background: rgba(0, 0, 0, 0.5);\r\n display: none;\r\n\r\n .popup_content {\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n background: #FFF;\r\n padding: 25px;\r\n border-radius: 0;\r\n max-width: 1140px;\r\n width: 100%;\r\n\r\n .close {\r\n position: absolute;\r\n top: 10px;\r\n right: 10px;\r\n cursor: pointer;\r\n }\r\n }\r\n}\r\n\r\n#fg-cron {\r\n margin: 10px 0;\r\n\r\n .countdown {\r\n background: $cGreen;\r\n color: #FFF;\r\n padding: 10px;\r\n }\r\n\r\n #cron-container {\r\n max-height: 300px;\r\n overflow-x: hidden;\r\n overflow-y: auto;\r\n\r\n .msg {\r\n font-size: 13px;\r\n padding: 5px;\r\n border-bottom: 1px solid #e8e8e8;\r\n }\r\n }\r\n}\r\n\r\n.card {\r\n background: #FFF;\r\n padding: 25px;\r\n border-radius: 6px;\r\n color: #000;\r\n font-size: 15px;\r\n max-width: 1280px;\r\n\r\n &.mb25 {\r\n margin-bottom: 25px;\r\n }\r\n\r\n .card-header {\r\n font-weight: 600;\r\n }\r\n\r\n .card-body {\r\n padding-top: 10px;\r\n\r\n table {\r\n border-collapse: collapse;\r\n\r\n th,\r\n td {\r\n font-size: 14px;\r\n\r\n &.bold {\r\n font-weight: 600;\r\n }\r\n\r\n &.text-right {\r\n text-align: right;\r\n }\r\n\r\n &.text-center {\r\n text-align: center;\r\n }\r\n\r\n .close-task {\r\n text-decoration: none;\r\n color: $cBlue;\r\n\r\n &:hover {\r\n color: $cRed;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n.finance-summary {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr 1fr 1fr;\r\n gap: 10px;\r\n\r\n .panel {\r\n background: #FFF;\r\n border-radius: 6px;\r\n padding: 15px;\r\n\r\n h1 {\r\n font-size: 20px;\r\n margin: 0;\r\n }\r\n\r\n span {\r\n font-size: 0.85em;\r\n }\r\n }\r\n}\r\n\r\n.finance-manager {\r\n display: grid;\r\n gap: 10px;\r\n grid-template-columns: 250px 1fr 500px;\r\n padding-top: 25px;\r\n\r\n .manage-menu {\r\n display: inline-block;\r\n margin-right: 10px;\r\n\r\n a {\r\n color: #333333;\r\n text-decoration: none;\r\n font-weight: 300;\r\n display: block;\r\n }\r\n }\r\n\r\n .actions {\r\n width: 100px;\r\n text-align: center;\r\n\r\n a {\r\n display: inline-flex;\r\n margin: 0 2px;\r\n height: 25px;\r\n width: 25px;\r\n align-items: center;\r\n justify-content: center;\r\n text-decoration: none;\r\n color: #000;\r\n border: 1px solid #e7e7e7;\r\n font-size: 11px;\r\n border-radius: 3px;\r\n transition: all 0.3s ease;\r\n\r\n &:hover {\r\n border: 1px solid $cBlue;\r\n }\r\n }\r\n }\r\n}\r\n\r\n.bootstrap-tagsinput {\r\n .tag {\r\n background: $cBlue;\r\n font-size: 13px;\r\n padding: 5px 10px;\r\n border-radius: 12px;\r\n\r\n [data-role=\"remove\"] {\r\n color: #FFF !important;\r\n\r\n &:hover {\r\n box-shadow: none !important;\r\n color: #000 !important\r\n }\r\n }\r\n }\r\n}\r\n\r\n.finance-tags {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 5px;\r\n\r\n a:not(.btn) {\r\n display: flex;\r\n width: 100%;\r\n text-decoration: none;\r\n color: $cBlack;\r\n\r\n &.zoom-100 {\r\n font-size: 1.2em;\r\n }\r\n\r\n &.zoom-90 {\r\n font-size: 1.15em;\r\n }\r\n\r\n &.zoom-80 {\r\n font-size: 1.1em;\r\n }\r\n\r\n &.zoom-70 {\r\n font-size: 1.05em;\r\n }\r\n\r\n &.zoom-60 {\r\n font-size: 1em;\r\n }\r\n\r\n &.zoom-50 {\r\n font-size: 0.95em;\r\n }\r\n\r\n &.zoom-40 {\r\n font-size: 0.9em;\r\n }\r\n\r\n &.zoom-30 {\r\n font-size: 0.85em;\r\n }\r\n\r\n &.zoom-20 {\r\n font-size: 0.8em;\r\n }\r\n\r\n &.zoom-10 {\r\n font-size: 0.75em;\r\n }\r\n\r\n &.zoom-0 {\r\n font-size: 0.7em;\r\n }\r\n }\r\n}\r\n\r\n.manage-menu {\r\n position: relative;\r\n\r\n .context-menu {\r\n border-left: 4px dotted #000;\r\n width: 1px;\r\n height: 100%;\r\n }\r\n\r\n .context-menu-container {\r\n position: absolute;\r\n display: none;\r\n background: #FFF;\r\n box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.1);\r\n top: 2px;\r\n left: 2px;\r\n\r\n ul {\r\n list-style-type: none;\r\n margin: 0;\r\n padding: 0;\r\n\r\n li {\r\n a {\r\n display: block;\r\n padding: 7px 15px;\r\n white-space: nowrap;\r\n\r\n &:hover {\r\n background: #f8f8f8;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n &:hover {\r\n .context-menu-container {\r\n display: block;\r\n }\r\n }\r\n}\r\n\r\n.wiki-categories {\r\n display: grid;\r\n gap: 10px;\r\n margin-top: 25px;\r\n grid-template-columns: 1fr 1fr 1fr 1fr;\r\n\r\n .category {\r\n background: #FFF;\r\n padding: 10px;\r\n\r\n .users {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr 1fr 1fr;\r\n gap: 5px;\r\n\r\n .user {\r\n display: flex;\r\n height: 25px;\r\n width: 25px;\r\n border-radius: 50%;\r\n background: #ccc;\r\n justify-content: center;\r\n align-items: center;\r\n color: #FFF;\r\n font-size: 12px;\r\n }\r\n }\r\n\r\n .actions {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n\r\n a {\r\n display: block;\r\n color: $cBlack;\r\n font-size: 13px;\r\n text-align: center;\r\n }\r\n }\r\n\r\n .title {\r\n margin-bottom: 5px;\r\n\r\n a {\r\n display: block;\r\n color: $cBlack;\r\n font-size: 13px;\r\n font-weight: 600;\r\n }\r\n }\r\n }\r\n}\r\n\r\n.bootstrap-datetimepicker-widget .picker-switch {\r\n a {\r\n display: block;\r\n color: #000;\r\n }\r\n}\r\n\r\n.gantt_users {\r\n display: flex;\r\n gap: 20px;\r\n}\r\n\r\n#g-results {\r\n background: #FFF;\r\n padding: 25px;\r\n}\r\n\r\n.g-menu-container {\r\n margin-bottom: 15px;\r\n\r\n .right-menu {\r\n display: none;\r\n }\r\n}\r\n\r\n.g-center {\r\n text-align: center;\r\n}\r\n\r\n.alert {\r\n background: $cGreen;\r\n border: 0;\r\n color: #FFF;\r\n}\r\n\r\n.tasks_main_view {\r\n display: flex;\r\n gap: 20px;\r\n align-items: flex-start;\r\n\r\n ._left_column {\r\n width: fit-content;\r\n min-width: 350px;\r\n max-width: 520px;\r\n padding: 0;\r\n background: transparent;\r\n border-right: 0;\r\n\r\n .filters_panel {\r\n background: linear-gradient(180deg, #fdfefe 0%, #f4f7fb 100%);\r\n border: 1px solid #dbe2ea;\r\n border-radius: 12px;\r\n padding: 16px;\r\n box-shadow: none;\r\n }\r\n\r\n .filters_panel_header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n margin-bottom: 14px;\r\n }\r\n\r\n .filters_panel_title {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n\r\n i {\r\n color: #1f3d72;\r\n }\r\n\r\n h3 {\r\n margin: 0;\r\n font-size: 16px;\r\n font-weight: 700;\r\n color: #1f3d72;\r\n }\r\n }\r\n\r\n .active_filters_badge {\r\n display: inline-flex;\r\n align-items: center;\r\n padding: 4px 10px;\r\n border-radius: 999px;\r\n font-size: 12px;\r\n color: #425466;\r\n background: #e9eff8;\r\n\r\n strong {\r\n margin-left: 4px;\r\n font-size: 13px;\r\n color: #1f3d72;\r\n }\r\n }\r\n\r\n .filters_controls {\r\n margin-bottom: 14px;\r\n padding: 12px;\r\n border-radius: 10px;\r\n border: 1px solid #dbe2ea;\r\n background: #fff;\r\n }\r\n\r\n .filters_label {\r\n display: block;\r\n margin-bottom: 6px;\r\n font-size: 12px;\r\n font-weight: 600;\r\n color: #425466;\r\n }\r\n\r\n select[name=\"filtr\"] {\r\n margin-bottom: 12px;\r\n height: 40px;\r\n border-color: #d1dae4;\r\n\r\n &:focus {\r\n border-color: #5f88e9;\r\n box-shadow: 0 0 0 3px rgba(95, 136, 233, 0.15);\r\n }\r\n }\r\n\r\n ._buttons {\r\n display: flex;\r\n gap: 8px;\r\n\r\n .btn {\r\n flex: 1;\r\n min-height: 34px;\r\n font-size: 12px;\r\n text-transform: uppercase;\r\n letter-spacing: 0.3px;\r\n }\r\n\r\n .btn-dark {\r\n background: #3d495e;\r\n\r\n &:hover {\r\n background: #2f394c;\r\n }\r\n }\r\n }\r\n\r\n .filters_section {\r\n border: 1px solid #dbe2ea;\r\n border-radius: 10px;\r\n background: #fff;\r\n margin-bottom: 12px;\r\n overflow: hidden;\r\n }\r\n\r\n .filters_section_header {\r\n display: flex;\r\n gap: 8px;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 10px 12px;\r\n background: #f4f7fb;\r\n border-bottom: 1px solid #e3eaf2;\r\n\r\n h4 {\r\n margin: 0;\r\n font-size: 14px;\r\n font-weight: 700;\r\n color: #243447;\r\n }\r\n\r\n .filters_search {\r\n max-width: 170px;\r\n height: 32px;\r\n font-size: 12px;\r\n padding: 4px 10px;\r\n border-color: #d2dbe6;\r\n }\r\n }\r\n\r\n .filters_section_list {\r\n max-height: 270px;\r\n overflow-y: auto;\r\n padding: 6px;\r\n }\r\n\r\n .filters_section._projects .filters_section_list {\r\n max-height: none;\r\n overflow: visible;\r\n }\r\n\r\n .filters_item {\r\n border-radius: 8px;\r\n transition: background 0.2s ease;\r\n\r\n &:hover {\r\n background: #f4f7fb;\r\n }\r\n }\r\n\r\n .project_row,\r\n ._user {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 8px;\r\n padding: 5px 7px;\r\n\r\n label {\r\n margin: 0;\r\n flex: 1;\r\n font-weight: 400;\r\n font-size: 14px;\r\n white-space: nowrap;\r\n }\r\n }\r\n\r\n .project_count {\r\n display: inline-block;\r\n margin-left: 4px;\r\n min-width: 26px;\r\n padding: 0 7px;\r\n border-radius: 999px;\r\n background: #1f3d72;\r\n color: #fff;\r\n font-weight: 700;\r\n font-size: 11px;\r\n line-height: 19px;\r\n text-align: center;\r\n vertical-align: middle;\r\n }\r\n\r\n .project_delete_inline {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 20px;\r\n height: 20px;\r\n border-radius: 5px;\r\n border: 1px solid #cc563d;\r\n background: #cc563d;\r\n color: #fff;\r\n text-decoration: none;\r\n transition: all 0.2s ease;\r\n margin: 1px 0;\r\n\r\n &:hover {\r\n background: #b74831;\r\n border-color: #b74831;\r\n }\r\n\r\n i {\r\n font-size: 10px;\r\n }\r\n }\r\n }\r\n\r\n ._right_column {\r\n flex: 1;\r\n max-width: none;\r\n min-width: 0;\r\n }\r\n}\r\n\r\n@media (max-width: 1200px) {\r\n .tasks_main_view {\r\n flex-direction: column;\r\n\r\n ._left_column,\r\n ._right_column {\r\n max-width: 100%;\r\n width: 100%;\r\n }\r\n }\r\n}\r\n\r\n.gantt-target {\r\n .gantt-container.gantt-draggable {\r\n cursor: grab;\r\n }\r\n\r\n .gantt-container.gantt-dragging {\r\n cursor: grabbing;\r\n }\r\n}\r\n\r\n#billing-summary {\r\n .card-header {\r\n padding: 10px;\r\n }\r\n\r\n .billing-kpi {\r\n border: 1px solid #dee2e6;\r\n border-radius: 6px;\r\n padding: 10px 12px;\r\n background: #ffffff;\r\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\r\n }\r\n\r\n .billing-kpi-label {\r\n font-size: 12px;\r\n color: #6c757d;\r\n margin-bottom: 3px;\r\n }\r\n\r\n .billing-kpi-value {\r\n font-size: 21px;\r\n font-weight: 700;\r\n line-height: 1.1;\r\n }\r\n\r\n .billing-details-row {\r\n display: none;\r\n }\r\n\r\n .billing-client-name {\r\n font-weight: 600;\r\n }\r\n\r\n .billing-table>thead>tr>th {\r\n background: #f8f9fa;\r\n }\r\n\r\n .billing-details-wrap {\r\n background: #f8fbff;\r\n }\r\n}\r\n\r\n/* sidebar submenu */\r\n\r\n/* vacations module */\r\n\r\n.vacation-type-badge {\r\n display: inline-block;\r\n padding: 2px 8px;\r\n border-radius: 4px;\r\n font-size: 12px;\r\n font-weight: 500;\r\n background: #e3f0ff;\r\n color: #2563eb;\r\n\r\n &.type-chorobowe {\r\n background: #fff3e0;\r\n color: #e65100;\r\n }\r\n\r\n &.type-inna_nieobecnosc {\r\n background: #f3e5f5;\r\n color: #7b1fa2;\r\n }\r\n}"]} \ No newline at end of file diff --git a/layout/style.scss b/layout/style.scss index 81d8108..4ab12e7 100644 --- a/layout/style.scss +++ b/layout/style.scss @@ -1750,7 +1750,7 @@ $sidebar-hover-bg: rgba(255, 255, 255, 0.08); .finance-manager { display: grid; gap: 10px; - grid-template-columns: 200px 1fr 500px; + grid-template-columns: 250px 1fr 500px; padding-top: 25px; .manage-menu { @@ -1999,36 +1999,248 @@ $sidebar-hover-bg: rgba(255, 255, 255, 0.08); .tasks_main_view { display: flex; gap: 20px; + align-items: flex-start; ._left_column { - padding: 25px; - background: #fcfcfc; - border-right: 1px solid #e8e8e8; - width: 350px; + width: fit-content; + min-width: 350px; + max-width: 520px; + padding: 0; + background: transparent; + border-right: 0; - label { - font-weight: 400; - font-size: 14px; + .filters_panel { + background: linear-gradient(180deg, #fdfefe 0%, #f4f7fb 100%); + border: 1px solid #dbe2ea; + border-radius: 12px; + padding: 16px; + box-shadow: none; + } + + .filters_panel_header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 14px; + } + + .filters_panel_title { + display: flex; + align-items: center; + gap: 8px; + + i { + color: #1f3d72; + } + + h3 { + margin: 0; + font-size: 16px; + font-weight: 700; + color: #1f3d72; + } + } + + .active_filters_badge { + display: inline-flex; + align-items: center; + padding: 4px 10px; + border-radius: 999px; + font-size: 12px; + color: #425466; + background: #e9eff8; + + strong { + margin-left: 4px; + font-size: 13px; + color: #1f3d72; + } + } + + .filters_controls { + margin-bottom: 14px; + padding: 12px; + border-radius: 10px; + border: 1px solid #dbe2ea; + background: #fff; + } + + .filters_label { + display: block; + margin-bottom: 6px; + font-size: 12px; + font-weight: 600; + color: #425466; } select[name="filtr"] { - margin-bottom: 10px; + margin-bottom: 12px; + height: 40px; + border-color: #d1dae4; + + &:focus { + border-color: #5f88e9; + box-shadow: 0 0 0 3px rgba(95, 136, 233, 0.15); + } } ._buttons { display: flex; - gap: 10px; - justify-content: space-between; + gap: 8px; .btn { flex: 1; + min-height: 34px; + font-size: 12px; + text-transform: uppercase; + letter-spacing: 0.3px; + } + + .btn-dark { + background: #3d495e; + + &:hover { + background: #2f394c; + } + } + } + + .filters_section { + border: 1px solid #dbe2ea; + border-radius: 10px; + background: #fff; + margin-bottom: 12px; + overflow: hidden; + } + + .filters_section_header { + display: flex; + gap: 8px; + align-items: center; + justify-content: space-between; + padding: 10px 12px; + background: #f4f7fb; + border-bottom: 1px solid #e3eaf2; + + h4 { + margin: 0; + font-size: 14px; + font-weight: 700; + color: #243447; + } + + .filters_search { + max-width: 170px; + height: 32px; + font-size: 12px; + padding: 4px 10px; + border-color: #d2dbe6; + } + } + + .filters_section_list { + max-height: 270px; + overflow-y: auto; + padding: 6px; + } + + .filters_section._projects .filters_section_list { + max-height: none; + overflow: visible; + } + + .filters_item { + border-radius: 8px; + transition: background 0.2s ease; + + &:hover { + background: #f4f7fb; + } + } + + .project_row, + ._user { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + padding: 5px 7px; + + label { + margin: 0; + flex: 1; + font-weight: 400; + font-size: 14px; + white-space: nowrap; + } + } + + .project_count { + display: inline-block; + margin-left: 4px; + min-width: 26px; + padding: 0 7px; + border-radius: 999px; + background: #1f3d72; + color: #fff; + font-weight: 700; + font-size: 11px; + line-height: 19px; + text-align: center; + vertical-align: middle; + } + + .project_delete_inline { + display: inline-flex; + align-items: center; + justify-content: center; + width: 20px; + height: 20px; + border-radius: 5px; + border: 1px solid #cc563d; + background: #cc563d; + color: #fff; + text-decoration: none; + transition: all 0.2s ease; + margin: 1px 0; + + &:hover { + background: #b74831; + border-color: #b74831; + } + + i { + font-size: 10px; } } } ._right_column { flex: 1; - max-width: calc(100% - 350px); + max-width: none; + min-width: 0; + } +} + +@media (max-width: 1200px) { + .tasks_main_view { + flex-direction: column; + + ._left_column, + ._right_column { + max-width: 100%; + width: 100%; + } + } +} + +.gantt-target { + .gantt-container.gantt-draggable { + cursor: grab; + } + + .gantt-container.gantt-dragging { + cursor: grabbing; } } diff --git a/templates/finances/fakturownia-import-panel.php b/templates/finances/fakturownia-import-panel.php new file mode 100644 index 0000000..824663a --- /dev/null +++ b/templates/finances/fakturownia-import-panel.php @@ -0,0 +1,148 @@ + + +
+
+

Import faktur z Fakturowni

+
+
+ fakturownia_last_summary ) && isset( $this -> fakturownia_last_summary['summary'] ) ): ?> +
+ Ostatni import: fakturownia_last_summary['at'] ?? '-' ); ?>
+ Zaimportowano: fakturownia_last_summary['summary']['imported'] ?? 0 ); ?>, + pominieto: fakturownia_last_summary['summary']['skipped'] ?? 0 ); ?>, + brak mapowan: fakturownia_last_summary['summary']['unmapped'] ?? 0 ); ?>, + bledy: fakturownia_last_summary['summary']['errors'] ?? 0 ); ?> +
+ + + fakturownia_pending_clients ) && count( $this -> fakturownia_pending_clients ) ): ?> +
Brakujace mapowania klientow
+ + + + + + + + + + fakturownia_pending_clients as $row ): ?> + + + + + + + +
Klient z FakturowniCRM klientAkcja
+
+ Klucz: | wystapienia: +
+
+ + + + +
+ + +
+ + + fakturownia_pending_items ) && count( $this -> fakturownia_pending_items ) ): ?> +
Brakujace mapowania produktow/uslug
+ + + + + + + + + + fakturownia_pending_items as $row ): ?> + + + + + + + +
Pozycja z fakturyKategoria finansowaAkcja
+
+ Klucz: | wystapienia: +
+
+ + + + +
+ + +
+ +
+
+ diff --git a/templates/finances/main-view.php b/templates/finances/main-view.php index 12fe66f..2c15a46 100644 --- a/templates/finances/main-view.php +++ b/templates/finances/main-view.php @@ -46,6 +46,9 @@ +
+ +
@@ -307,4 +310,4 @@ $(function() { $(this).parents('.input-group').children('input').trigger('click'); }); }); - \ No newline at end of file + diff --git a/templates/tasks/main_view.php b/templates/tasks/main_view.php index 162887e..c6e3027 100644 --- a/templates/tasks/main_view.php +++ b/templates/tasks/main_view.php @@ -1,48 +1,70 @@
- - -
-

Projekty

- projects as $project ):?> -
-
- - user['id'], 'projects', 'project_delete' ) ):?> - - - - +
+
+
+ +

Filtry

+
+ Aktywne: 0 +
+
+ + + +
+
+
+

Projekty

+ +
+
+ projects as $project ):?> +
+
+ + user['id'], 'projects', 'project_delete' ) ):?> + + + + +
+
+ +
+
+ user['id'] == 1 ):?> +
+
+

Użytkownicy

+ +
+
+ users as $user ):?> +
+ +
+
- +
- user['id'] == 1 ):?> -
-

Użytkownicy

- users as $user ):?> -
- -
- -
-
@@ -134,79 +156,23 @@
-