Full Code of solidtime-io/solidtime for AI

main 192c8c3b887a cached
1208 files
3.9 MB
1.1M tokens
2769 symbols
1 requests
Download .txt
Showing preview only (4,320K chars total). Download the full file or copy to clipboard to get everything.
Repository: solidtime-io/solidtime
Branch: main
Commit: 192c8c3b887a
Files: 1208
Total size: 3.9 MB

Directory structure:
gitextract_ryuvl2mb/

├── .editorconfig
├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── 1_bug_report.yml
│   │   └── config.yml
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── build-onpremise.yml
│       ├── build-private.yml
│       ├── build-public.yml
│       ├── generate-api-docs.yml
│       ├── npm-build.yml
│       ├── npm-format-check.yml
│       ├── npm-lint.yml
│       ├── npm-publish-api.yml
│       ├── npm-publish-ui.yml
│       ├── npm-typecheck.yml
│       ├── phpstan.yml
│       ├── phpunit.yml
│       ├── pint.yml
│       └── playwright.yml
├── .gitignore
├── .prettierignore
├── .prettierrc.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── SECURITY.md
├── app/
│   ├── Actions/
│   │   ├── Fortify/
│   │   │   ├── CreateNewUser.php
│   │   │   ├── PasswordValidationRules.php
│   │   │   ├── ResetUserPassword.php
│   │   │   ├── UpdateUserPassword.php
│   │   │   └── UpdateUserProfileInformation.php
│   │   └── Jetstream/
│   │       ├── AddOrganizationMember.php
│   │       ├── CreateOrganization.php
│   │       ├── DeleteOrganization.php
│   │       ├── DeleteUser.php
│   │       ├── InviteOrganizationMember.php
│   │       ├── RemoveOrganizationMember.php
│   │       ├── UpdateMemberRole.php
│   │       ├── UpdateOrganization.php
│   │       └── ValidateOrganizationDeletion.php
│   ├── Console/
│   │   ├── Commands/
│   │   │   ├── Admin/
│   │   │   │   ├── OrganizationDeleteCommand.php
│   │   │   │   ├── UserCreateCommand.php
│   │   │   │   └── UserVerifyCommand.php
│   │   │   ├── Auth/
│   │   │   │   └── AuthSendReminderForExpiringApiTokensCommand.php
│   │   │   ├── Correction/
│   │   │   │   └── CorrectionPlaceholderMembersCommand.php
│   │   │   ├── Report/
│   │   │   │   └── ReportSetExpiredToPrivateCommand.php
│   │   │   ├── SelfHost/
│   │   │   │   ├── SelfHostCheckForUpdateCommand.php
│   │   │   │   ├── SelfHostDatabaseConsistency.php
│   │   │   │   ├── SelfHostGenerateKeysCommand.php
│   │   │   │   └── SelfHostTelemetryCommand.php
│   │   │   ├── Test/
│   │   │   │   ├── TestEmailCommand.php
│   │   │   │   ├── TestJobCommand.php
│   │   │   │   └── TestOutputCommand.php
│   │   │   └── TimeEntry/
│   │   │       └── TimeEntrySendStillRunningMailsCommand.php
│   │   └── Kernel.php
│   ├── Enums/
│   │   ├── CurrencyFormat.php
│   │   ├── DateFormat.php
│   │   ├── ExportFormat.php
│   │   ├── IntervalFormat.php
│   │   ├── NumberFormat.php
│   │   ├── Role.php
│   │   ├── TimeEntryAggregationType.php
│   │   ├── TimeEntryAggregationTypeInterval.php
│   │   ├── TimeEntryRoundingType.php
│   │   ├── TimeFormat.php
│   │   └── Weekday.php
│   ├── Events/
│   │   ├── AfterCreateOrganization.php
│   │   ├── BeforeOrganizationDeletion.php
│   │   ├── DatabaseSeederAfterSeed.php
│   │   ├── DatabaseSeederBeforeDelete.php
│   │   ├── MemberMadeToPlaceholder.php
│   │   ├── MemberRemoved.php
│   │   └── NewsletterRegistered.php
│   ├── Exceptions/
│   │   ├── Api/
│   │   │   ├── ApiException.php
│   │   │   ├── CanNotDeleteUserWhoIsOwnerOfOrganizationWithMultipleMembers.php
│   │   │   ├── CanNotRemoveOwnerFromOrganization.php
│   │   │   ├── ChangingRoleOfPlaceholderIsNotAllowed.php
│   │   │   ├── ChangingRoleToPlaceholderIsNotAllowed.php
│   │   │   ├── EntityStillInUseApiException.php
│   │   │   ├── FeatureIsNotAvailableInFreePlanApiException.php
│   │   │   ├── InactiveUserCanNotBeUsedApiException.php
│   │   │   ├── InvitationForTheEmailAlreadyExistsApiException.php
│   │   │   ├── OnlyOwnerCanChangeOwnership.php
│   │   │   ├── OnlyPlaceholdersCanBeMergedIntoAnotherMember.php
│   │   │   ├── OrganizationHasNoSubscriptionButMultipleMembersException.php
│   │   │   ├── OrganizationNeedsAtLeastOneOwner.php
│   │   │   ├── OverlappingTimeEntryApiException.php
│   │   │   ├── PdfRendererIsNotConfiguredException.php
│   │   │   ├── PersonalAccessClientIsNotConfiguredException.php
│   │   │   ├── ThisPlaceholderCanNotBeInvitedUseTheMergeToolInsteadException.php
│   │   │   ├── TimeEntryCanNotBeRestartedApiException.php
│   │   │   ├── TimeEntryStillRunningApiException.php
│   │   │   ├── UserIsAlreadyMemberOfOrganizationApiException.php
│   │   │   ├── UserIsAlreadyMemberOfProjectApiException.php
│   │   │   └── UserNotPlaceholderApiException.php
│   │   ├── Handler.php
│   │   └── MovedToApiException.php
│   ├── Extensions/
│   │   ├── Auditing/
│   │   │   └── Resolvers/
│   │   │       └── CustomIpAddressResolver.php
│   │   ├── Fortify/
│   │   │   ├── CustomLoginResponse.php
│   │   │   └── CustomTwoFactorLoginResponse.php
│   │   └── Scramble/
│   │       ├── ApiExceptionTypeToSchema.php
│   │       └── PaginatedResourceCollectionTypeToSchema.php
│   ├── Filament/
│   │   ├── Resources/
│   │   │   ├── AuditResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── CreateAudit.php
│   │   │   │       ├── ListAudits.php
│   │   │   │       └── ViewAudit.php
│   │   │   ├── AuditResource.php
│   │   │   ├── ClientResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── CreateClient.php
│   │   │   │       ├── EditClient.php
│   │   │   │       └── ListClients.php
│   │   │   ├── ClientResource.php
│   │   │   ├── FailedJobResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── ListFailedJobs.php
│   │   │   │       └── ViewFailedJobs.php
│   │   │   ├── FailedJobResource.php
│   │   │   ├── OrganizationInvitationResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── EditOrganizationInvitation.php
│   │   │   │       ├── ListOrganizationInvitations.php
│   │   │   │       └── ViewOrganizationInvitation.php
│   │   │   ├── OrganizationInvitationResource.php
│   │   │   ├── OrganizationResource/
│   │   │   │   ├── Actions/
│   │   │   │   │   └── DeleteOrganization.php
│   │   │   │   ├── Pages/
│   │   │   │   │   ├── CreateOrganization.php
│   │   │   │   │   ├── EditOrganization.php
│   │   │   │   │   ├── ListOrganizations.php
│   │   │   │   │   └── ViewOrganization.php
│   │   │   │   └── RelationManagers/
│   │   │   │       ├── InvitationsRelationManager.php
│   │   │   │       └── UsersRelationManager.php
│   │   │   ├── OrganizationResource.php
│   │   │   ├── ProjectMemberResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── CreateProjectMember.php
│   │   │   │       ├── EditProjectMember.php
│   │   │   │       ├── ListProjectMembers.php
│   │   │   │       └── ViewProjectMembers.php
│   │   │   ├── ProjectMemberResource.php
│   │   │   ├── ProjectResource/
│   │   │   │   ├── Pages/
│   │   │   │   │   ├── CreateProject.php
│   │   │   │   │   ├── EditProject.php
│   │   │   │   │   └── ListProjects.php
│   │   │   │   └── RelationManagers/
│   │   │   │       └── ProjectMembersRelationManager.php
│   │   │   ├── ProjectResource.php
│   │   │   ├── ReportResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── EditReport.php
│   │   │   │       ├── ListReports.php
│   │   │   │       └── ViewReport.php
│   │   │   ├── ReportResource.php
│   │   │   ├── TagResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── CreateTag.php
│   │   │   │       ├── EditTag.php
│   │   │   │       └── ListTags.php
│   │   │   ├── TagResource.php
│   │   │   ├── TaskResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── CreateTask.php
│   │   │   │       ├── EditTask.php
│   │   │   │       └── ListTasks.php
│   │   │   ├── TaskResource.php
│   │   │   ├── TimeEntryResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── CreateTimeEntry.php
│   │   │   │       ├── EditTimeEntry.php
│   │   │   │       └── ListTimeEntries.php
│   │   │   ├── TimeEntryResource.php
│   │   │   ├── TokenResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── ListTokens.php
│   │   │   │       └── ViewToken.php
│   │   │   ├── TokenResource.php
│   │   │   ├── UserResource/
│   │   │   │   ├── Actions/
│   │   │   │   │   └── DeleteUser.php
│   │   │   │   ├── Pages/
│   │   │   │   │   ├── CreateUser.php
│   │   │   │   │   ├── EditUser.php
│   │   │   │   │   ├── ListUsers.php
│   │   │   │   │   └── ViewUser.php
│   │   │   │   └── RelationManagers/
│   │   │   │       ├── OrganizationsRelationManager.php
│   │   │   │       └── OwnedOrganizationsRelationManager.php
│   │   │   └── UserResource.php
│   │   └── Widgets/
│   │       ├── ActiveUserOverview.php
│   │       ├── ServerOverview.php
│   │       ├── TimeEntriesCreated.php
│   │       ├── TimeEntriesImported.php
│   │       └── UserRegistrations.php
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── Api/
│   │   │   │   └── V1/
│   │   │   │       ├── ApiTokenController.php
│   │   │   │       ├── ChartController.php
│   │   │   │       ├── ClientController.php
│   │   │   │       ├── Controller.php
│   │   │   │       ├── CurrencyController.php
│   │   │   │       ├── ExportController.php
│   │   │   │       ├── ImportController.php
│   │   │   │       ├── InvitationController.php
│   │   │   │       ├── MemberController.php
│   │   │   │       ├── OrganizationController.php
│   │   │   │       ├── ProjectController.php
│   │   │   │       ├── ProjectMemberController.php
│   │   │   │       ├── Public/
│   │   │   │       │   └── ReportController.php
│   │   │   │       ├── ReportController.php
│   │   │   │       ├── TagController.php
│   │   │   │       ├── TaskController.php
│   │   │   │       ├── TimeEntryController.php
│   │   │   │       ├── UserController.php
│   │   │   │       ├── UserMembershipController.php
│   │   │   │       └── UserTimeEntryController.php
│   │   │   ├── Controller.php
│   │   │   └── Web/
│   │   │       ├── Controller.php
│   │   │       ├── DashboardController.php
│   │   │       ├── HealthCheckController.php
│   │   │       └── HomeController.php
│   │   ├── Kernel.php
│   │   ├── Middleware/
│   │   │   ├── Authenticate.php
│   │   │   ├── CheckOrganizationBlocked.php
│   │   │   ├── EncryptCookies.php
│   │   │   ├── EnsureEmailIsVerified.php
│   │   │   ├── ForceHttps.php
│   │   │   ├── ForceJsonResponse.php
│   │   │   ├── HandleInertiaRequests.php
│   │   │   ├── PreventRequestsDuringMaintenance.php
│   │   │   ├── RedirectIfAuthenticated.php
│   │   │   ├── ShareInertiaData.php
│   │   │   ├── TrimStrings.php
│   │   │   ├── TrustProxies.php
│   │   │   ├── ValidateSignature.php
│   │   │   └── VerifyCsrfToken.php
│   │   ├── Requests/
│   │   │   └── V1/
│   │   │       ├── ApiToken/
│   │   │       │   └── ApiTokenStoreRequest.php
│   │   │       ├── BaseFormRequest.php
│   │   │       ├── Client/
│   │   │       │   ├── ClientIndexRequest.php
│   │   │       │   ├── ClientStoreRequest.php
│   │   │       │   └── ClientUpdateRequest.php
│   │   │       ├── Import/
│   │   │       │   └── ImportRequest.php
│   │   │       ├── Invitation/
│   │   │       │   ├── InvitationIndexRequest.php
│   │   │       │   └── InvitationStoreRequest.php
│   │   │       ├── Member/
│   │   │       │   ├── MemberDestroyRequest.php
│   │   │       │   ├── MemberIndexRequest.php
│   │   │       │   ├── MemberMergeIntoRequest.php
│   │   │       │   └── MemberUpdateRequest.php
│   │   │       ├── Organization/
│   │   │       │   └── OrganizationUpdateRequest.php
│   │   │       ├── Project/
│   │   │       │   ├── ProjectIndexRequest.php
│   │   │       │   ├── ProjectStoreRequest.php
│   │   │       │   └── ProjectUpdateRequest.php
│   │   │       ├── ProjectMember/
│   │   │       │   ├── ProjectMemberIndexRequest.php
│   │   │       │   ├── ProjectMemberStoreRequest.php
│   │   │       │   └── ProjectMemberUpdateRequest.php
│   │   │       ├── Report/
│   │   │       │   ├── ReportIndexRequest.php
│   │   │       │   ├── ReportStoreRequest.php
│   │   │       │   └── ReportUpdateRequest.php
│   │   │       ├── Tag/
│   │   │       │   ├── TagIndexRequest.php
│   │   │       │   ├── TagStoreRequest.php
│   │   │       │   └── TagUpdateRequest.php
│   │   │       ├── Task/
│   │   │       │   ├── TaskIndexRequest.php
│   │   │       │   ├── TaskStoreRequest.php
│   │   │       │   └── TaskUpdateRequest.php
│   │   │       └── TimeEntry/
│   │   │           ├── TimeEntryAggregateExportRequest.php
│   │   │           ├── TimeEntryAggregateRequest.php
│   │   │           ├── TimeEntryDestroyMultipleRequest.php
│   │   │           ├── TimeEntryIndexExportRequest.php
│   │   │           ├── TimeEntryIndexRequest.php
│   │   │           ├── TimeEntryStoreRequest.php
│   │   │           ├── TimeEntryUpdateMultipleRequest.php
│   │   │           └── TimeEntryUpdateRequest.php
│   │   └── Resources/
│   │       ├── PaginatedResourceCollection.php
│   │       └── V1/
│   │           ├── ApiToken/
│   │           │   ├── ApiTokenCollection.php
│   │           │   ├── ApiTokenResource.php
│   │           │   └── ApiTokenWithAccessTokenResource.php
│   │           ├── BaseResource.php
│   │           ├── Client/
│   │           │   ├── ClientCollection.php
│   │           │   └── ClientResource.php
│   │           ├── Invitation/
│   │           │   ├── InvitationCollection.php
│   │           │   └── InvitationResource.php
│   │           ├── Member/
│   │           │   ├── MemberCollection.php
│   │           │   ├── MemberResource.php
│   │           │   ├── PersonalMembershipCollection.php
│   │           │   └── PersonalMembershipResource.php
│   │           ├── Organization/
│   │           │   └── OrganizationResource.php
│   │           ├── Project/
│   │           │   ├── ProjectCollection.php
│   │           │   └── ProjectResource.php
│   │           ├── ProjectMember/
│   │           │   ├── ProjectMemberCollection.php
│   │           │   └── ProjectMemberResource.php
│   │           ├── Report/
│   │           │   ├── DetailedReportResource.php
│   │           │   ├── DetailedWithDataReportResource.php
│   │           │   ├── ReportCollection.php
│   │           │   └── ReportResource.php
│   │           ├── Tag/
│   │           │   ├── TagCollection.php
│   │           │   └── TagResource.php
│   │           ├── Task/
│   │           │   ├── TaskCollection.php
│   │           │   └── TaskResource.php
│   │           ├── TimeEntry/
│   │           │   ├── TimeEntryCollection.php
│   │           │   └── TimeEntryResource.php
│   │           └── User/
│   │               └── UserResource.php
│   ├── Jobs/
│   │   ├── RecalculateSpentTimeForProject.php
│   │   ├── RecalculateSpentTimeForTask.php
│   │   └── Test/
│   │       └── TestJob.php
│   ├── Listeners/
│   │   └── RemovePlaceholder.php
│   ├── Mail/
│   │   ├── AuthApiTokenExpirationReminderMail.php
│   │   ├── AuthApiTokenExpiredMail.php
│   │   ├── OrganizationInvitationMail.php
│   │   └── TimeEntryStillRunningMail.php
│   ├── Models/
│   │   ├── Audit.php
│   │   ├── Client.php
│   │   ├── Concerns/
│   │   │   ├── CustomAuditable.php
│   │   │   └── HasUuids.php
│   │   ├── FailedJob.php
│   │   ├── Member.php
│   │   ├── Organization.php
│   │   ├── OrganizationInvitation.php
│   │   ├── Passport/
│   │   │   ├── AuthCode.php
│   │   │   ├── Client.php
│   │   │   ├── RefreshToken.php
│   │   │   └── Token.php
│   │   ├── Project.php
│   │   ├── ProjectMember.php
│   │   ├── Report.php
│   │   ├── Tag.php
│   │   ├── Task.php
│   │   ├── TimeEntry.php
│   │   └── User.php
│   ├── Policies/
│   │   └── OrganizationPolicy.php
│   ├── Providers/
│   │   ├── AppServiceProvider.php
│   │   ├── AuthServiceProvider.php
│   │   ├── EventServiceProvider.php
│   │   ├── Filament/
│   │   │   └── AdminPanelProvider.php
│   │   ├── FortifyServiceProvider.php
│   │   ├── JetstreamServiceProvider.php
│   │   ├── RouteServiceProvider.php
│   │   └── TelescopeServiceProvider.php
│   ├── Rules/
│   │   ├── ColorRule.php
│   │   └── CurrencyRule.php
│   └── Service/
│       ├── ApiService.php
│       ├── BillableRateService.php
│       ├── BillingContract.php
│       ├── ColorService.php
│       ├── CurrencyService.php
│       ├── DashboardService.php
│       ├── DeletionService.php
│       ├── Dto/
│       │   └── ReportPropertiesDto.php
│       ├── Export/
│       │   ├── ExportException.php
│       │   └── ExportService.php
│       ├── Import/
│       │   ├── ImportDatabaseHelper.php
│       │   ├── ImportService.php
│       │   └── Importers/
│       │       ├── ClockifyProjectsImporter.php
│       │       ├── ClockifyTimeEntriesImporter.php
│       │       ├── DefaultImporter.php
│       │       ├── GenericProjectsImporter.php
│       │       ├── GenericTimeEntriesImporter.php
│       │       ├── HarvestClientsImporter.php
│       │       ├── HarvestProjectsImporter.php
│       │       ├── HarvestTimeEntriesImporter.php
│       │       ├── ImportException.php
│       │       ├── ImporterContract.php
│       │       ├── ImporterProvider.php
│       │       ├── ReportDto.php
│       │       ├── SolidtimeImporter.php
│       │       ├── TogglDataImporter.php
│       │       └── TogglTimeEntriesImporter.php
│       ├── IntervalService.php
│       ├── InvitationService.php
│       ├── IpLookup/
│       │   ├── IpLookupResponseDto.php
│       │   ├── IpLookupServiceContract.php
│       │   └── NoIpLookupService.php
│       ├── LocalizationService.php
│       ├── MemberService.php
│       ├── OrganizationInvitationService.php
│       ├── OrganizationService.php
│       ├── PermissionStore.php
│       ├── ReportExport/
│       │   ├── CsvExport.php
│       │   ├── TimeEntriesDetailedCsvExport.php
│       │   ├── TimeEntriesDetailedExport.php
│       │   └── TimeEntriesReportExport.php
│       ├── ReportService.php
│       ├── TimeEntryAggregationService.php
│       ├── TimeEntryFilter.php
│       ├── TimeEntryService.php
│       ├── TimezoneService.php
│       └── UserService.php
├── artisan
├── bootstrap/
│   ├── app.php
│   └── cache/
│       └── .gitignore
├── components.json
├── composer.json
├── config/
│   ├── app.php
│   ├── audit.php
│   ├── auth.php
│   ├── broadcasting.php
│   ├── cache.php
│   ├── cors.php
│   ├── database.php
│   ├── excel.php
│   ├── filament.php
│   ├── filesystems.php
│   ├── fortify.php
│   ├── hashing.php
│   ├── jetstream.php
│   ├── logging.php
│   ├── mail.php
│   ├── modules.php
│   ├── octane.php
│   ├── passport.php
│   ├── queue.php
│   ├── scheduling.php
│   ├── scramble.php
│   ├── services.php
│   ├── session.php
│   ├── telescope.php
│   ├── trustedproxy.php
│   └── view.php
├── database/
│   ├── .gitignore
│   ├── factories/
│   │   ├── AuditFactory.php
│   │   ├── ClientFactory.php
│   │   ├── FailedJobFactory.php
│   │   ├── MemberFactory.php
│   │   ├── OrganizationFactory.php
│   │   ├── OrganizationInvitationFactory.php
│   │   ├── Passport/
│   │   │   ├── ClientFactory.php
│   │   │   └── TokenFactory.php
│   │   ├── ProjectFactory.php
│   │   ├── ProjectMemberFactory.php
│   │   ├── ReportFactory.php
│   │   ├── TagFactory.php
│   │   ├── TaskFactory.php
│   │   ├── TimeEntryFactory.php
│   │   └── UserFactory.php
│   ├── migrations/
│   │   ├── 2014_10_12_000000_create_users_table.php
│   │   ├── 2014_10_12_100000_create_password_reset_tokens_table.php
│   │   ├── 2014_10_12_200000_add_two_factor_columns_to_users_table.php
│   │   ├── 2016_06_01_000001_create_oauth_auth_codes_table.php
│   │   ├── 2016_06_01_000002_create_oauth_access_tokens_table.php
│   │   ├── 2016_06_01_000003_create_oauth_refresh_tokens_table.php
│   │   ├── 2016_06_01_000004_create_oauth_clients_table.php
│   │   ├── 2016_06_01_000005_create_oauth_personal_access_clients_table.php
│   │   ├── 2018_08_08_100000_create_telescope_entries_table.php
│   │   ├── 2019_08_19_000000_create_failed_jobs_table.php
│   │   ├── 2019_12_14_000001_create_personal_access_tokens_table.php
│   │   ├── 2020_05_21_100000_create_organizations_table.php
│   │   ├── 2020_05_21_200000_create_organization_user_table.php
│   │   ├── 2020_05_21_300000_create_organization_invitations_table.php
│   │   ├── 2024_01_16_161030_create_sessions_table.php
│   │   ├── 2024_01_20_110218_create_clients_table.php
│   │   ├── 2024_01_20_110439_create_projects_table.php
│   │   ├── 2024_01_20_110444_create_tasks_table.php
│   │   ├── 2024_01_20_110452_create_tags_table.php
│   │   ├── 2024_01_20_110837_create_time_entries_table.php
│   │   ├── 2024_03_26_171253_create_project_members_table.php
│   │   ├── 2024_04_11_150130_create_jobs_table.php
│   │   ├── 2024_04_12_095010_create_cache_table.php
│   │   ├── 2024_05_07_134711_move_from_user_id_to_member_id_in_project_members_table.php
│   │   ├── 2024_05_07_141842_move_from_user_id_to_member_id_in_time_entries_table.php
│   │   ├── 2024_05_13_171020_rename_table_organization_user_to_members.php
│   │   ├── 2024_05_22_151226_add_client_id_to_time_entries_table.php
│   │   ├── 2024_05_30_175801_add_is_billable_column_to_projects_table.php
│   │   ├── 2024_05_30_175825_add_is_imported_column_to_time_entries_table.php
│   │   ├── 2024_06_01_000001_create_oauth_device_codes_table.php
│   │   ├── 2024_06_07_113443_change_member_id_foreign_keys_to_restrict_on_delete.php
│   │   ├── 2024_06_10_161831_reset_billable_rates_with_zero_as_value.php
│   │   ├── 2024_06_21_122754_add_is_archived_columns_to_projects_and_clients_table.php
│   │   ├── 2024_06_24_114433_add_done_at_to_tasks_table.php
│   │   ├── 2024_07_02_134307_add_estimated_time_to_projects_and_tasks_table.php
│   │   ├── 2024_07_03_145445_change_data_type_of_id_column_in_failed_jobs_table.php
│   │   ├── 2024_07_18_080906_add_still_active_email_sent_at_to_time_entries_table.php
│   │   ├── 2024_08_01_104840_create_reports_table.php
│   │   ├── 2024_09_02_094105_create_audits_table.php
│   │   ├── 2024_09_18_120203_add_spent_time_to_projects_and_tasks_table.php
│   │   ├── 2024_10_01_143608_add_employees_can_see_billable_rates_to_organizations_table.php
│   │   ├── 2024_11_04_164807_add_foreign_key_to_organizations_and_members_table.php
│   │   ├── 2024_11_04_170614_add_foreign_keys_to_oauth_tables.php
│   │   ├── 2025_04_03_101827_add_localization_columns_to_organizations_table.php
│   │   ├── 2025_04_25_202047_change_data_type_for_spent_time_columns.php
│   │   ├── 2025_05_06_152804_fix_typos_in_organizations_table_format_columns.php
│   │   ├── 2025_05_16_075757_add_foreign_key_for_current_team_id_in_users_table.php
│   │   ├── 2025_06_30_095942_remove_oauth_personal_access_clients_table.php
│   │   ├── 2025_06_30_132538_update_oauth_clients_table.php
│   │   ├── 2025_07_15_105949_hash_oauth_clients.php
│   │   ├── 2025_07_17_104903_add_reminder_sent_at_to_oauth_access_tokens_table.php
│   │   ├── 2025_10_02_000001_add_prevent_overlapping_time_entries_to_organizations_table.php
│   │   ├── 2025_10_16_000001_extend_time_entry_description.php
│   │   └── 2025_10_24_120845_add_employees_can_manage_tasks_to_organizations_table.php
│   ├── schema/
│   │   └── pgsql_test-schema.sql
│   └── seeders/
│       └── DatabaseSeeder.php
├── docker/
│   ├── local/
│   │   ├── 8.3/
│   │   │   ├── Dockerfile
│   │   │   ├── php.ini
│   │   │   ├── start-container
│   │   │   └── supervisord.conf
│   │   ├── minio/
│   │   │   └── create_bucket.sh
│   │   └── pgsql/
│   │       └── create-testing-database.sql
│   └── prod/
│       ├── Dockerfile
│       ├── LICENSE
│       └── deployment/
│           ├── healthcheck
│           ├── octane/
│           │   └── FrankenPHP/
│           │       ├── Caddyfile
│           │       └── supervisord.frankenphp.conf
│           ├── php.ini
│           ├── start-container
│           ├── supervisord.conf
│           ├── supervisord.horizon.conf
│           ├── supervisord.reverb.conf
│           ├── supervisord.scheduler.conf
│           └── supervisord.worker.conf
├── docker-compose.yml
├── e2e/
│   ├── auth.spec.ts
│   ├── calendar-settings.spec.ts
│   ├── calendar.spec.ts
│   ├── clients.spec.ts
│   ├── command-palette.spec.ts
│   ├── dashboard.spec.ts
│   ├── import-export.spec.ts
│   ├── members.spec.ts
│   ├── organization.spec.ts
│   ├── profile.spec.ts
│   ├── project-members.spec.ts
│   ├── projects.spec.ts
│   ├── reporting-detailed.spec.ts
│   ├── reporting.spec.ts
│   ├── shared-reports.spec.ts
│   ├── tags.spec.ts
│   ├── tasks.spec.ts
│   ├── time.spec.ts
│   ├── timetracker.spec.ts
│   └── utils/
│       ├── api.ts
│       ├── currentTimeEntry.ts
│       ├── mailpit.ts
│       ├── members.ts
│       ├── money.ts
│       ├── reporting.ts
│       ├── table.ts
│       └── tags.ts
├── eslint.config.mjs
├── jsconfig.json
├── lang/
│   └── en/
│       ├── auth.php
│       ├── enum.php
│       ├── exceptions.php
│       ├── importer.php
│       ├── pagination.php
│       ├── passwords.php
│       └── validation.php
├── openapi.json
├── package.json
├── phpstan.neon
├── phpunit.xml
├── pint.json
├── playwright/
│   ├── config.ts
│   └── fixtures.ts
├── playwright.config.ts
├── postcss.config.js
├── public/
│   ├── .htaccess
│   ├── desktop-version/
│   │   ├── latest-linux.yml
│   │   ├── latest-mac.yml
│   │   └── latest.yml
│   ├── favicons/
│   │   ├── browserconfig.xml
│   │   └── site.webmanifest
│   ├── index.php
│   ├── robots.txt
│   └── security.txt
├── resources/
│   ├── css/
│   │   ├── app.css
│   │   └── filament/
│   │       └── admin/
│   │           ├── tailwind.config.js
│   │           └── theme.css
│   ├── js/
│   │   ├── Components/
│   │   │   ├── ActionMessage.vue
│   │   │   ├── ActionSection.vue
│   │   │   ├── ApplicationLogo.vue
│   │   │   ├── ApplicationMark.vue
│   │   │   ├── AuthenticationCard.vue
│   │   │   ├── AuthenticationCardLogo.vue
│   │   │   ├── Banner.vue
│   │   │   ├── Billing/
│   │   │   │   └── BillingBanner.vue
│   │   │   ├── CommandPalette/
│   │   │   │   ├── CommandPaletteProvider.vue
│   │   │   │   └── index.ts
│   │   │   ├── Common/
│   │   │   │   ├── Card.vue
│   │   │   │   ├── Client/
│   │   │   │   │   ├── ClientCreateModal.vue
│   │   │   │   │   ├── ClientEditModal.vue
│   │   │   │   │   ├── ClientMoreOptionsDropdown.vue
│   │   │   │   │   ├── ClientMultiselectDropdown.vue
│   │   │   │   │   ├── ClientTable.vue
│   │   │   │   │   ├── ClientTableHeading.vue
│   │   │   │   │   └── ClientTableRow.vue
│   │   │   │   ├── Invitation/
│   │   │   │   │   ├── InvitationMoreOptionsDropdown.vue
│   │   │   │   │   ├── InvitationTable.vue
│   │   │   │   │   ├── InvitationTableHeading.vue
│   │   │   │   │   └── InvitationTableRow.vue
│   │   │   │   ├── Member/
│   │   │   │   │   ├── MemberBillableRateModal.vue
│   │   │   │   │   ├── MemberBillableSelect.vue
│   │   │   │   │   ├── MemberCombobox.vue
│   │   │   │   │   ├── MemberDeleteModal.vue
│   │   │   │   │   ├── MemberEditModal.vue
│   │   │   │   │   ├── MemberInviteModal.vue
│   │   │   │   │   ├── MemberMakePlaceholderModal.vue
│   │   │   │   │   ├── MemberMergeModal.vue
│   │   │   │   │   ├── MemberMoreOptionsDropdown.vue
│   │   │   │   │   ├── MemberMultiselectDropdown.vue
│   │   │   │   │   ├── MemberOwnershipTransferConfirmModal.vue
│   │   │   │   │   ├── MemberRoleSelect.vue
│   │   │   │   │   ├── MemberTable.vue
│   │   │   │   │   ├── MemberTableHeading.vue
│   │   │   │   │   └── MemberTableRow.vue
│   │   │   │   ├── Notification/
│   │   │   │   │   └── Notification.vue
│   │   │   │   ├── Organization/
│   │   │   │   │   └── OrganizationBillableRateModal.vue
│   │   │   │   ├── PageTitle.vue
│   │   │   │   ├── Project/
│   │   │   │   │   ├── BaseFilterBadge.vue
│   │   │   │   │   ├── ProjectClientFilterBadge.vue
│   │   │   │   │   ├── ProjectDropdown.vue
│   │   │   │   │   ├── ProjectEditModal.vue
│   │   │   │   │   ├── ProjectMoreOptionsDropdown.vue
│   │   │   │   │   ├── ProjectMultiselectDropdown.vue
│   │   │   │   │   ├── ProjectStatusFilterBadge.vue
│   │   │   │   │   ├── ProjectTable.vue
│   │   │   │   │   ├── ProjectTableHeading.vue
│   │   │   │   │   ├── ProjectTableRow.vue
│   │   │   │   │   ├── ProjectsFilterDropdown.vue
│   │   │   │   │   └── constants.ts
│   │   │   │   ├── ProjectMember/
│   │   │   │   │   ├── ProjectMemberBillableRateModal.vue
│   │   │   │   │   ├── ProjectMemberCreateModal.vue
│   │   │   │   │   ├── ProjectMemberEditModal.vue
│   │   │   │   │   ├── ProjectMemberMoreOptionsDropdown.vue
│   │   │   │   │   ├── ProjectMemberTable.vue
│   │   │   │   │   ├── ProjectMemberTableHeading.vue
│   │   │   │   │   └── ProjectMemberTableRow.vue
│   │   │   │   ├── Report/
│   │   │   │   │   ├── ReportCreateModal.vue
│   │   │   │   │   ├── ReportEditModal.vue
│   │   │   │   │   ├── ReportMoreOptionsDropdown.vue
│   │   │   │   │   ├── ReportSaveButton.vue
│   │   │   │   │   ├── ReportTable.vue
│   │   │   │   │   ├── ReportTableHeading.vue
│   │   │   │   │   └── ReportTableRow.vue
│   │   │   │   ├── Reporting/
│   │   │   │   │   ├── ReportingChart.vue
│   │   │   │   │   ├── ReportingExportButton.vue
│   │   │   │   │   ├── ReportingExportModal.vue
│   │   │   │   │   ├── ReportingFilterBadge.vue
│   │   │   │   │   ├── ReportingFilterBar.vue
│   │   │   │   │   ├── ReportingGroupBySelect.vue
│   │   │   │   │   ├── ReportingOverview.vue
│   │   │   │   │   ├── ReportingPieChart.vue
│   │   │   │   │   ├── ReportingRoundingControls.vue
│   │   │   │   │   ├── ReportingRow.vue
│   │   │   │   │   └── ReportingTabNavbar.vue
│   │   │   │   ├── StatCard.vue
│   │   │   │   ├── TabBar/
│   │   │   │   │   ├── TabBar.vue
│   │   │   │   │   └── TabBarItem.vue
│   │   │   │   ├── TableHeading.vue
│   │   │   │   ├── Tag/
│   │   │   │   │   ├── TagEditModal.vue
│   │   │   │   │   ├── TagMoreOptionsDropdown.vue
│   │   │   │   │   ├── TagTable.vue
│   │   │   │   │   ├── TagTableHeading.vue
│   │   │   │   │   └── TagTableRow.vue
│   │   │   │   ├── Task/
│   │   │   │   │   ├── TaskCreateModal.vue
│   │   │   │   │   ├── TaskEditModal.vue
│   │   │   │   │   ├── TaskMoreOptionsDropdown.vue
│   │   │   │   │   ├── TaskMultiselectDropdown.vue
│   │   │   │   │   ├── TaskTable.vue
│   │   │   │   │   ├── TaskTableHeading.vue
│   │   │   │   │   └── TaskTableRow.vue
│   │   │   │   ├── UpgradeBadge.vue
│   │   │   │   ├── UpgradeModal.vue
│   │   │   │   └── User/
│   │   │   │       └── UserTimezoneMismatchModal.vue
│   │   │   ├── ConfirmationModal.vue
│   │   │   ├── ConfirmsPassword.vue
│   │   │   ├── CurrentSidebarTimer.vue
│   │   │   ├── Dashboard/
│   │   │   │   ├── ActivityGraphCard.vue
│   │   │   │   ├── DashboardCard.vue
│   │   │   │   ├── DayOverviewCardChart.vue
│   │   │   │   ├── DayOverviewCardEntry.vue
│   │   │   │   ├── LastSevenDaysCard.vue
│   │   │   │   ├── ProjectsChartCard.vue
│   │   │   │   ├── RecentlyTrackedTasksCard.vue
│   │   │   │   ├── RecentlyTrackedTasksCardEntry.vue
│   │   │   │   ├── TeamActivityCard.vue
│   │   │   │   ├── TeamActivityCardEntry.vue
│   │   │   │   ├── ThisWeekOverview.vue
│   │   │   │   └── ThisWeekReportingTable.vue
│   │   │   ├── DropdownLink.vue
│   │   │   ├── FormSection.vue
│   │   │   ├── NavLink.vue
│   │   │   ├── NavigationSidebarItem.vue
│   │   │   ├── NavigationSidebarLink.vue
│   │   │   ├── NotificationContainer.vue
│   │   │   ├── OrganizationSwitcher.vue
│   │   │   ├── ResponsiveNavLink.vue
│   │   │   ├── SectionBorder.vue
│   │   │   ├── SectionTitle.vue
│   │   │   ├── TableRow.vue
│   │   │   ├── TimeTracker.vue
│   │   │   ├── UpdateSidebarNotification.vue
│   │   │   ├── UserSettingsIcon.vue
│   │   │   └── ui/
│   │   │       ├── alert-dialog/
│   │   │       │   ├── AlertDialog.vue
│   │   │       │   ├── AlertDialogAction.vue
│   │   │       │   ├── AlertDialogCancel.vue
│   │   │       │   ├── AlertDialogContent.vue
│   │   │       │   ├── AlertDialogDescription.vue
│   │   │       │   ├── AlertDialogFooter.vue
│   │   │       │   ├── AlertDialogHeader.vue
│   │   │       │   ├── AlertDialogTitle.vue
│   │   │       │   ├── AlertDialogTrigger.vue
│   │   │       │   └── index.ts
│   │   │       ├── calendar/
│   │   │       │   ├── Calendar.vue
│   │   │       │   ├── CalendarCell.vue
│   │   │       │   ├── CalendarCellTrigger.vue
│   │   │       │   ├── CalendarDateInput.vue
│   │   │       │   ├── CalendarGrid.vue
│   │   │       │   ├── CalendarGridBody.vue
│   │   │       │   ├── CalendarGridHead.vue
│   │   │       │   ├── CalendarGridRow.vue
│   │   │       │   ├── CalendarHeadCell.vue
│   │   │       │   ├── CalendarHeader.vue
│   │   │       │   ├── CalendarHeading.vue
│   │   │       │   ├── CalendarNextButton.vue
│   │   │       │   ├── CalendarPrevButton.vue
│   │   │       │   └── index.ts
│   │   │       ├── dialog/
│   │   │       │   ├── Dialog.vue
│   │   │       │   ├── DialogClose.vue
│   │   │       │   ├── DialogContent.vue
│   │   │       │   ├── DialogDescription.vue
│   │   │       │   ├── DialogFooter.vue
│   │   │       │   ├── DialogHeader.vue
│   │   │       │   ├── DialogScrollContent.vue
│   │   │       │   ├── DialogTitle.vue
│   │   │       │   ├── DialogTrigger.vue
│   │   │       │   └── index.ts
│   │   │       ├── dropdown-menu/
│   │   │       │   ├── DropdownMenu.vue
│   │   │       │   ├── DropdownMenuCheckboxItem.vue
│   │   │       │   ├── DropdownMenuContent.vue
│   │   │       │   ├── DropdownMenuGroup.vue
│   │   │       │   ├── DropdownMenuItem.vue
│   │   │       │   ├── DropdownMenuLabel.vue
│   │   │       │   ├── DropdownMenuRadioGroup.vue
│   │   │       │   ├── DropdownMenuRadioItem.vue
│   │   │       │   ├── DropdownMenuSeparator.vue
│   │   │       │   ├── DropdownMenuShortcut.vue
│   │   │       │   ├── DropdownMenuSub.vue
│   │   │       │   ├── DropdownMenuSubContent.vue
│   │   │       │   ├── DropdownMenuSubTrigger.vue
│   │   │       │   ├── DropdownMenuTrigger.vue
│   │   │       │   └── index.ts
│   │   │       ├── label/
│   │   │       │   ├── Label.vue
│   │   │       │   └── index.ts
│   │   │       ├── number-field/
│   │   │       │   ├── NumberField.vue
│   │   │       │   ├── NumberFieldContent.vue
│   │   │       │   ├── NumberFieldDecrement.vue
│   │   │       │   ├── NumberFieldIncrement.vue
│   │   │       │   ├── NumberFieldInput.vue
│   │   │       │   └── index.ts
│   │   │       ├── select/
│   │   │       │   ├── Select.vue
│   │   │       │   ├── SelectContent.vue
│   │   │       │   ├── SelectGroup.vue
│   │   │       │   ├── SelectItem.vue
│   │   │       │   ├── SelectItemText.vue
│   │   │       │   ├── SelectLabel.vue
│   │   │       │   ├── SelectScrollDownButton.vue
│   │   │       │   ├── SelectScrollUpButton.vue
│   │   │       │   ├── SelectSeparator.vue
│   │   │       │   ├── SelectTrigger.vue
│   │   │       │   ├── SelectValue.vue
│   │   │       │   └── index.ts
│   │   │       ├── switch/
│   │   │       │   ├── Switch.vue
│   │   │       │   └── index.ts
│   │   │       ├── table/
│   │   │       │   ├── Table.vue
│   │   │       │   ├── TableBody.vue
│   │   │       │   ├── TableCaption.vue
│   │   │       │   ├── TableCell.vue
│   │   │       │   ├── TableEmpty.vue
│   │   │       │   ├── TableFooter.vue
│   │   │       │   ├── TableHead.vue
│   │   │       │   ├── TableHeader.vue
│   │   │       │   ├── TableRow.vue
│   │   │       │   └── index.ts
│   │   │       └── tabs/
│   │   │           ├── Tabs.vue
│   │   │           ├── TabsContent.vue
│   │   │           ├── TabsList.vue
│   │   │           ├── TabsTrigger.vue
│   │   │           └── index.ts
│   │   ├── Layouts/
│   │   │   └── AppLayout.vue
│   │   ├── Pages/
│   │   │   ├── API/
│   │   │   │   ├── Index.vue
│   │   │   │   └── Partials/
│   │   │   │       └── ApiTokenManager.vue
│   │   │   ├── Auth/
│   │   │   │   ├── ConfirmPassword.vue
│   │   │   │   ├── ForgotPassword.vue
│   │   │   │   ├── Login.vue
│   │   │   │   ├── Register.vue
│   │   │   │   ├── ResetPassword.vue
│   │   │   │   ├── TwoFactorChallenge.vue
│   │   │   │   └── VerifyEmail.vue
│   │   │   ├── Calendar.vue
│   │   │   ├── Clients.vue
│   │   │   ├── Dashboard.vue
│   │   │   ├── Import.vue
│   │   │   ├── Members.vue
│   │   │   ├── PrivacyPolicy.vue
│   │   │   ├── Profile/
│   │   │   │   ├── Partials/
│   │   │   │   │   ├── ApiTokensForm.vue
│   │   │   │   │   ├── DeleteUserForm.vue
│   │   │   │   │   ├── LogoutOtherBrowserSessionsForm.vue
│   │   │   │   │   ├── ThemeForm.vue
│   │   │   │   │   ├── TwoFactorAuthenticationForm.vue
│   │   │   │   │   ├── UpdatePasswordForm.vue
│   │   │   │   │   └── UpdateProfileInformationForm.vue
│   │   │   │   └── Show.vue
│   │   │   ├── ProjectShow.vue
│   │   │   ├── Projects.vue
│   │   │   ├── Reporting.vue
│   │   │   ├── ReportingDetailed.vue
│   │   │   ├── ReportingShared.vue
│   │   │   ├── SharedReport.vue
│   │   │   ├── Tags.vue
│   │   │   ├── Teams/
│   │   │   │   ├── Create.vue
│   │   │   │   ├── Partials/
│   │   │   │   │   ├── CreateTeamForm.vue
│   │   │   │   │   ├── DeleteTeamForm.vue
│   │   │   │   │   ├── ExportData.vue
│   │   │   │   │   ├── ImportData.vue
│   │   │   │   │   ├── OrganizationBillableRate.vue
│   │   │   │   │   ├── OrganizationFormatSettings.vue
│   │   │   │   │   ├── OrganizationTimeEntrySettings.vue
│   │   │   │   │   ├── TeamMemberManager.vue
│   │   │   │   │   └── UpdateTeamNameForm.vue
│   │   │   │   └── Show.vue
│   │   │   ├── TermsOfService.vue
│   │   │   ├── Time.vue
│   │   │   └── Welcome.vue
│   │   ├── app.ts
│   │   ├── bootstrap.js
│   │   ├── lib/
│   │   │   └── utils.ts
│   │   ├── packages/
│   │   │   ├── api/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── package.json
│   │   │   │   ├── src/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── openapi.json.client.ts
│   │   │   │   ├── tsconfig.json
│   │   │   │   └── vite.config.js
│   │   │   └── ui/
│   │   │       ├── .gitignore
│   │   │       ├── package.json
│   │   │       ├── src/
│   │   │       │   ├── Badge.vue
│   │   │       │   ├── BillableRateModal.vue
│   │   │       │   ├── Buttons/
│   │   │       │   │   ├── Button.vue
│   │   │       │   │   ├── DangerButton.vue
│   │   │       │   │   ├── PrimaryButton.vue
│   │   │       │   │   ├── SecondaryButton.vue
│   │   │       │   │   └── index.ts
│   │   │       │   ├── CardTitle.vue
│   │   │       │   ├── Client/
│   │   │       │   │   ├── ClientDropdown.vue
│   │   │       │   │   └── ClientDropdownItem.vue
│   │   │       │   ├── CommandPalette/
│   │   │       │   │   ├── CommandPalette.vue
│   │   │       │   │   ├── CommandPaletteTypes.ts
│   │   │       │   │   └── index.ts
│   │   │       │   ├── DialogModal.vue
│   │   │       │   ├── EstimatedTimeProgress.vue
│   │   │       │   ├── EstimatedTimeSection.vue
│   │   │       │   ├── FullCalendar/
│   │   │       │   │   ├── CalendarSettingsPopover.vue
│   │   │       │   │   ├── FullCalendarDayHeader.vue
│   │   │       │   │   ├── FullCalendarEventContent.vue
│   │   │       │   │   ├── TimeEntryCalendar.vue
│   │   │       │   │   ├── calendarSettings.ts
│   │   │       │   │   ├── idleStatusPlugin.ts
│   │   │       │   │   └── useVisualSnap.ts
│   │   │       │   ├── GroupedItemsCountButton.vue
│   │   │       │   ├── Icons/
│   │   │       │   │   ├── BillableIcon.vue
│   │   │       │   │   ├── DollarIcon.vue
│   │   │       │   │   ├── EuroIcon.vue
│   │   │       │   │   └── ListFilterIcon.vue
│   │   │       │   ├── Input/
│   │   │       │   │   ├── BillableRateInput.vue
│   │   │       │   │   ├── BillableToggleButton.vue
│   │   │       │   │   ├── Checkbox.vue
│   │   │       │   │   ├── DatePicker.vue
│   │   │       │   │   ├── DateRangePicker.vue
│   │   │       │   │   ├── Dropdown.vue
│   │   │       │   │   ├── DurationHumanInput.vue
│   │   │       │   │   ├── EstimatedTimeInput.vue
│   │   │       │   │   ├── InputError.vue
│   │   │       │   │   ├── InputLabel.vue
│   │   │       │   │   ├── MultiselectDropdown.vue
│   │   │       │   │   ├── TextInput.vue
│   │   │       │   │   ├── TextareaInput.vue
│   │   │       │   │   ├── TimePickerSimple.vue
│   │   │       │   │   └── TimeRangeSelector.vue
│   │   │       │   ├── LoadingSpinner.vue
│   │   │       │   ├── MainContainer.vue
│   │   │       │   ├── Modal.vue
│   │   │       │   ├── Project/
│   │   │       │   │   ├── ProjectBadge.vue
│   │   │       │   │   ├── ProjectBillableRateModal.vue
│   │   │       │   │   ├── ProjectBillableSelect.vue
│   │   │       │   │   ├── ProjectColorSelector.vue
│   │   │       │   │   ├── ProjectCreateModal.vue
│   │   │       │   │   ├── ProjectDropdownItem.vue
│   │   │       │   │   └── ProjectEditBillableSection.vue
│   │   │       │   ├── Tag/
│   │   │       │   │   ├── TagBadge.vue
│   │   │       │   │   ├── TagCreateModal.vue
│   │   │       │   │   └── TagDropdown.vue
│   │   │       │   ├── TimeEntry/
│   │   │       │   │   ├── TimeEntryAggregateRow.vue
│   │   │       │   │   ├── TimeEntryCreateModal.vue
│   │   │       │   │   ├── TimeEntryDescriptionInput.vue
│   │   │       │   │   ├── TimeEntryEditModal.vue
│   │   │       │   │   ├── TimeEntryGroupedTable.vue
│   │   │       │   │   ├── TimeEntryMassActionRow.vue
│   │   │       │   │   ├── TimeEntryMassUpdateModal.vue
│   │   │       │   │   ├── TimeEntryMoreOptionsDropdown.vue
│   │   │       │   │   ├── TimeEntryRangeSelector.vue
│   │   │       │   │   ├── TimeEntryRow.vue
│   │   │       │   │   ├── TimeEntryRowDurationInput.vue
│   │   │       │   │   ├── TimeEntryRowHeading.vue
│   │   │       │   │   └── TimeEntryRowTagDropdown.vue
│   │   │       │   ├── TimeTracker/
│   │   │       │   │   ├── TimeTrackerControls.vue
│   │   │       │   │   ├── TimeTrackerMoreOptionsDropdown.vue
│   │   │       │   │   ├── TimeTrackerProjectTaskDropdown.vue
│   │   │       │   │   ├── TimeTrackerRangeSelector.vue
│   │   │       │   │   ├── TimeTrackerRecentlyTrackedEntry.vue
│   │   │       │   │   ├── TimeTrackerRunningInDifferentOrganizationOverlay.vue
│   │   │       │   │   └── TimeTrackerTagDropdown.vue
│   │   │       │   ├── TimeTrackerStartStop.vue
│   │   │       │   ├── TimezoneMismatchModal.vue
│   │   │       │   ├── accordion/
│   │   │       │   │   ├── Accordion.vue
│   │   │       │   │   ├── AccordionContent.vue
│   │   │       │   │   ├── AccordionItem.vue
│   │   │       │   │   ├── AccordionTrigger.vue
│   │   │       │   │   └── index.ts
│   │   │       │   ├── command/
│   │   │       │   │   ├── Command.vue
│   │   │       │   │   ├── CommandGroup.vue
│   │   │       │   │   ├── CommandInput.vue
│   │   │       │   │   ├── CommandItem.vue
│   │   │       │   │   ├── CommandList.vue
│   │   │       │   │   ├── CommandSeparator.vue
│   │   │       │   │   ├── CommandShortcut.vue
│   │   │       │   │   └── index.ts
│   │   │       │   ├── field/
│   │   │       │   │   ├── Field.vue
│   │   │       │   │   ├── FieldContent.vue
│   │   │       │   │   ├── FieldDescription.vue
│   │   │       │   │   ├── FieldError.vue
│   │   │       │   │   ├── FieldGroup.vue
│   │   │       │   │   ├── FieldLabel.vue
│   │   │       │   │   ├── FieldLegend.vue
│   │   │       │   │   ├── FieldSeparator.vue
│   │   │       │   │   ├── FieldSet.vue
│   │   │       │   │   ├── FieldTitle.vue
│   │   │       │   │   └── index.ts
│   │   │       │   ├── index.ts
│   │   │       │   ├── popover/
│   │   │       │   │   ├── Popover.vue
│   │   │       │   │   ├── PopoverContent.vue
│   │   │       │   │   ├── PopoverTrigger.vue
│   │   │       │   │   └── index.ts
│   │   │       │   ├── range-calendar/
│   │   │       │   │   ├── RangeCalendar.vue
│   │   │       │   │   ├── RangeCalendarCell.vue
│   │   │       │   │   ├── RangeCalendarCellTrigger.vue
│   │   │       │   │   ├── RangeCalendarGrid.vue
│   │   │       │   │   ├── RangeCalendarGridBody.vue
│   │   │       │   │   ├── RangeCalendarGridHead.vue
│   │   │       │   │   ├── RangeCalendarGridRow.vue
│   │   │       │   │   ├── RangeCalendarHeadCell.vue
│   │   │       │   │   ├── RangeCalendarHeader.vue
│   │   │       │   │   ├── RangeCalendarHeading.vue
│   │   │       │   │   ├── RangeCalendarNextButton.vue
│   │   │       │   │   ├── RangeCalendarPrevButton.vue
│   │   │       │   │   └── index.ts
│   │   │       │   ├── separator/
│   │   │       │   │   ├── Separator.vue
│   │   │       │   │   └── index.ts
│   │   │       │   ├── tooltip/
│   │   │       │   │   ├── Tooltip.vue
│   │   │       │   │   ├── TooltipContent.vue
│   │   │       │   │   ├── TooltipProvider.vue
│   │   │       │   │   ├── TooltipTrigger.vue
│   │   │       │   │   └── index.ts
│   │   │       │   └── utils/
│   │   │       │       ├── cn.ts
│   │   │       │       ├── color.ts
│   │   │       │       ├── money.ts
│   │   │       │       ├── number.ts
│   │   │       │       ├── random.ts
│   │   │       │       ├── select.ts
│   │   │       │       ├── settings.ts
│   │   │       │       └── time.ts
│   │   │       ├── styles.css
│   │   │       ├── tailwind.theme.js
│   │   │       ├── tsconfig.json
│   │   │       └── vite.config.js
│   │   ├── types/
│   │   │   ├── dom.d.ts
│   │   │   ├── dom.ts
│   │   │   ├── global.d.ts
│   │   │   ├── inertia.d.ts
│   │   │   ├── jetstream.ts
│   │   │   ├── models.d.ts
│   │   │   ├── models.ts
│   │   │   ├── projects.d.ts
│   │   │   ├── reporting.ts
│   │   │   ├── time-entries.d.ts
│   │   │   ├── vite-env.d.ts
│   │   │   └── vue-shim.d.ts
│   │   ├── utils/
│   │   │   ├── billing.ts
│   │   │   ├── commandPaletteCommands.ts
│   │   │   ├── feedback.ts
│   │   │   ├── fetchAllPages.ts
│   │   │   ├── format.ts
│   │   │   ├── init.ts
│   │   │   ├── money.ts
│   │   │   ├── notification.ts
│   │   │   ├── permissions.ts
│   │   │   ├── prefetch.ts
│   │   │   ├── roles.ts
│   │   │   ├── session.ts
│   │   │   ├── theme.ts
│   │   │   ├── useAggregatedTimeEntriesQuery.ts
│   │   │   ├── useClients.ts
│   │   │   ├── useClientsQuery.ts
│   │   │   ├── useCommandPalette.ts
│   │   │   ├── useCssVariable.ts
│   │   │   ├── useCurrentTimeEntry.ts
│   │   │   ├── useInvitations.ts
│   │   │   ├── useMembers.ts
│   │   │   ├── useMembersQuery.ts
│   │   │   ├── useOrganization.ts
│   │   │   ├── useOrganizationQuery.ts
│   │   │   ├── useProjectMembers.ts
│   │   │   ├── useProjectMembersQuery.ts
│   │   │   ├── useProjects.ts
│   │   │   ├── useProjectsQuery.ts
│   │   │   ├── useReporting.ts
│   │   │   ├── useReportsQuery.ts
│   │   │   ├── useTags.ts
│   │   │   ├── useTagsQuery.ts
│   │   │   ├── useTasks.ts
│   │   │   ├── useTasksQuery.ts
│   │   │   ├── useTimeEntriesCalendarQuery.ts
│   │   │   ├── useTimeEntriesInfiniteQuery.ts
│   │   │   ├── useTimeEntriesMutations.ts
│   │   │   ├── useTimeEntriesReportQuery.ts
│   │   │   └── useUser.ts
│   │   ├── ziggy.d.ts
│   │   └── ziggy.js
│   ├── markdown/
│   │   ├── policy.md
│   │   └── terms.md
│   ├── testfiles/
│   │   ├── clockify_projects_import_test_1.csv
│   │   ├── clockify_time_entries_import_test_1.csv
│   │   ├── clockify_time_entries_import_test_2.csv
│   │   ├── clockify_time_entries_import_test_3.csv
│   │   ├── generic_projects_import_test_1.csv
│   │   ├── generic_time_entries_import_test_1.csv
│   │   ├── harvest_clients_import_test_1.csv
│   │   ├── harvest_projects_import_test_1.csv
│   │   ├── harvest_time_entries_import_test_1.csv
│   │   ├── solidtime_import_test_1/
│   │   │   ├── clients.csv
│   │   │   ├── members.csv
│   │   │   ├── meta.json
│   │   │   ├── organization_invitations.csv
│   │   │   ├── organizations.csv
│   │   │   ├── project_members.csv
│   │   │   ├── projects.csv
│   │   │   ├── tags.csv
│   │   │   ├── tasks.csv
│   │   │   └── time_entries.csv
│   │   ├── toggl_data_import_test_1/
│   │   │   ├── clients.json
│   │   │   ├── projects.json
│   │   │   ├── projects_users/
│   │   │   │   ├── 401.json
│   │   │   │   ├── 402.json
│   │   │   │   └── 403.json
│   │   │   ├── tags.json
│   │   │   ├── tasks/
│   │   │   │   ├── 401.json
│   │   │   │   ├── 402.json
│   │   │   │   └── 403.json
│   │   │   └── workspace_users.json
│   │   ├── toggl_data_import_test_2/
│   │   │   ├── clients.json
│   │   │   ├── projects.json
│   │   │   ├── projects_users/
│   │   │   │   ├── 401.json
│   │   │   │   ├── 402.json
│   │   │   │   └── 403.json
│   │   │   ├── tags.json
│   │   │   ├── tasks/
│   │   │   │   ├── 401.json
│   │   │   │   ├── 402.json
│   │   │   │   └── 403.json
│   │   │   └── workspace_users.json
│   │   ├── toggl_time_entries_import_test_1.csv
│   │   └── toggl_time_entries_import_test_2.csv
│   └── views/
│       ├── app.blade.php
│       ├── auth/
│       │   └── oauth/
│       │       └── authorize.blade.php
│       ├── emails/
│       │   ├── auth-api-expiration-reminder.blade.php
│       │   ├── auth-api-token-expired.blade.php
│       │   ├── organization-invitation.blade.php
│       │   └── time-entry-still-running.blade.php
│       ├── filament/
│       │   └── widgets/
│       │       └── server-overview.blade.php
│       ├── reports/
│       │   ├── time-entry-aggregate/
│       │   │   ├── pdf-footer.blade.php
│       │   │   ├── pdf.blade.php
│       │   │   └── spreadsheet.blade.php
│       │   └── time-entry-index/
│       │       ├── pdf-footer.blade.php
│       │       └── pdf.blade.php
│       └── vendor/
│           └── mail/
│               ├── html/
│               │   ├── button.blade.php
│               │   ├── footer.blade.php
│               │   ├── header.blade.php
│               │   ├── layout.blade.php
│               │   ├── message.blade.php
│               │   ├── panel.blade.php
│               │   ├── subcopy.blade.php
│               │   ├── table.blade.php
│               │   └── themes/
│               │       └── default.css
│               └── text/
│                   ├── button.blade.php
│                   ├── footer.blade.php
│                   ├── header.blade.php
│                   ├── layout.blade.php
│                   ├── message.blade.php
│                   ├── panel.blade.php
│                   ├── subcopy.blade.php
│                   └── table.blade.php
├── routes/
│   ├── api.php
│   └── web.php
├── storage/
│   ├── app/
│   │   └── .gitignore
│   ├── framework/
│   │   ├── .gitignore
│   │   ├── cache/
│   │   │   └── .gitignore
│   │   ├── sessions/
│   │   │   └── .gitignore
│   │   ├── testing/
│   │   │   └── .gitignore
│   │   └── views/
│   │       └── .gitignore
│   └── logs/
│       └── .gitignore
├── tailwind.config.js
├── tests/
│   ├── CreatesApplication.php
│   ├── Feature/
│   │   ├── AuthenticationTest.php
│   │   ├── BrowserSessionsTest.php
│   │   ├── CreateOrganizationTest.php
│   │   ├── DeleteAccountTest.php
│   │   ├── DeleteOrganizationTest.php
│   │   ├── EmailVerificationTest.php
│   │   ├── InviteTeamMemberTest.php
│   │   ├── LeaveTeamTest.php
│   │   ├── PasswordConfirmationTest.php
│   │   ├── PasswordResetTest.php
│   │   ├── ProfileInformationTest.php
│   │   ├── RegistrationTest.php
│   │   ├── RemoveTeamMemberTest.php
│   │   ├── TwoFactorAuthenticationSettingsTest.php
│   │   ├── UpdatePasswordTest.php
│   │   ├── UpdateTeamMemberRoleTest.php
│   │   └── UpdateTeamTest.php
│   ├── TestCase.php
│   ├── TestCaseWithDatabase.php
│   └── Unit/
│       ├── Console/
│       │   ├── Commands/
│       │   │   ├── Admin/
│       │   │   │   ├── OrganizationDeleteCommandTest.php
│       │   │   │   ├── UserCreateCommandCommandTest.php
│       │   │   │   └── UserVerifyCommandTest.php
│       │   │   ├── Auth/
│       │   │   │   └── AuthSendReminderForExpiringApiTokensCommandTest.php
│       │   │   ├── Correction/
│       │   │   │   └── CorrectionPlaceholderMembersCommandTest.php
│       │   │   ├── Report/
│       │   │   │   └── ReportSetExpiredToPrivateCommandTest.php
│       │   │   ├── SelfHost/
│       │   │   │   ├── SelfHostCheckForUpdateCommandTest.php
│       │   │   │   ├── SelfHostDatabaseConsistencyCommandTest.php
│       │   │   │   ├── SelfHostGenerateKeysCommandTest.php
│       │   │   │   └── SelfHostTelemetryCommandTest.php
│       │   │   └── TimeEntry/
│       │   │       └── TimeEntrySendStillRunningMailsCommandTest.php
│       │   └── KernelTest.php
│       ├── Database/
│       │   ├── MigrationTest.php
│       │   └── SeederTest.php
│       ├── Endpoint/
│       │   ├── Api/
│       │   │   └── V1/
│       │   │       ├── ApiEndpointTestAbstract.php
│       │   │       ├── ApiTokenEndpointTest.php
│       │   │       ├── ChartEndpointTest.php
│       │   │       ├── ClientEndpointTest.php
│       │   │       ├── CurrencyEndpointTest.php
│       │   │       ├── ExportEndpointTest.php
│       │   │       ├── ImportEndpointTest.php
│       │   │       ├── InvitationEndpointTest.php
│       │   │       ├── MemberEndpointTest.php
│       │   │       ├── OrganizationEndpointTest.php
│       │   │       ├── ProjectEndpointTest.php
│       │   │       ├── ProjectMemberEndpointTest.php
│       │   │       ├── Public/
│       │   │       │   └── PublicReportEndpointTest.php
│       │   │       ├── ReportEndpointTest.php
│       │   │       ├── TagEndpointTest.php
│       │   │       ├── TaskEndpointTest.php
│       │   │       ├── TimeEntryEndpointTest.php
│       │   │       ├── UserEndpointTest.php
│       │   │       ├── UserMembershipEndpointTest.php
│       │   │       └── UserTimeEntryEndpointTest.php
│       │   └── Web/
│       │       ├── DashboardEndpointTest.php
│       │       ├── EndpointTestAbstract.php
│       │       ├── HealthCheckEndpointTest.php
│       │       └── HomeEndpointTest.php
│       ├── Filament/
│       │   ├── FilamentTestCase.php
│       │   ├── Resources/
│       │   │   ├── AuditResourceTest.php
│       │   │   ├── ClientResourceTest.php
│       │   │   ├── FailedJobResourceTest.php
│       │   │   ├── OrganizationInvitationResourceTest.php
│       │   │   ├── OrganizationResourceTest.php
│       │   │   ├── ProjectResourceTest.php
│       │   │   ├── ReportResourceTest.php
│       │   │   ├── TagResourceTest.php
│       │   │   ├── TaskResourceTest.php
│       │   │   ├── TimeEntryResourceTest.php
│       │   │   ├── TokenResourceTest.php
│       │   │   └── UserResourceTest.php
│       │   └── Widgets/
│       │       └── ServerOverviewWidgetTest.php
│       ├── Jobs/
│       │   ├── RecalculateSpentTimeForProjectTest.php
│       │   ├── RecalculateSpentTimeForTaskTest.php
│       │   └── Test/
│       │       └── TestJobTest.php
│       ├── Mail/
│       │   ├── AuthApiTokenExpirationReminderMailTest.php
│       │   ├── AuthApiTokenExpiredMailTest.php
│       │   ├── OrganizationInvitationMailTest.php
│       │   └── TimeEntryStillRunningMailTest.php
│       ├── Middleware/
│       │   ├── CheckOrganizationBlockedMiddlewareTest.php
│       │   ├── EnsureEmailIsVerifiedMiddlewareTest.php
│       │   ├── ForceHttpsMiddlewareTest.php
│       │   ├── HandleInertiaRequestsMiddlewareTest.php
│       │   └── MiddlewareTestAbstract.php
│       ├── Model/
│       │   ├── ClientModelTest.php
│       │   ├── MemberModelTest.php
│       │   ├── ModelTestAbstract.php
│       │   ├── OrganizationModelTest.php
│       │   ├── Passport/
│       │   │   └── TokenModelTest.php
│       │   ├── ProjectMemberModelTest.php
│       │   ├── ProjectModelTest.php
│       │   ├── ReportModelTest.php
│       │   ├── TagModelTest.php
│       │   ├── TaskModelTest.php
│       │   ├── TimeEntryModelTest.php
│       │   └── UserModelTest.php
│       ├── Rules/
│       │   ├── ColorRuleTest.php
│       │   └── CurrencyRuleTest.php
│       └── Service/
│           ├── BillableRateServiceTest.php
│           ├── CurrencyServiceTest.php
│           ├── DashboardServiceTest.php
│           ├── DeletionServiceTest.php
│           ├── Export/
│           │   └── ExportServiceTest.php
│           ├── Import/
│           │   ├── ImportDatabaseHelperTest.php
│           │   ├── ImportServiceTest.php
│           │   └── Importers/
│           │       ├── ClockifyProjectsImporterTest.php
│           │       ├── ClockifyTimeEntriesImporterTest.php
│           │       ├── GenericProjectsImporterTest.php
│           │       ├── GenericTimeEntriesImporterTest.php
│           │       ├── HarvestClientsImporterTest.php
│           │       ├── HarvestProjectsImporterTest.php
│           │       ├── HarvestTimeEntriesImporterTest.php
│           │       ├── ImporterProviderTest.php
│           │       ├── ImporterTestAbstract.php
│           │       ├── SolidtimeImporterTest.php
│           │       ├── TogglDataImporterTest.php
│           │       └── TogglTimeEntriesImporterTest.php
│           ├── IntervalServiceTest.php
│           ├── LocalizationServiceTest.php
│           ├── MemberServiceTest.php
│           ├── PermissionStoreTest.php
│           ├── TimeEntryAggregationServiceTest.php
│           ├── TimeEntryFilterTest.php
│           ├── TimezoneServiceTest.php
│           └── UserServiceTest.php
├── tsconfig.json
├── vite-module-loader.js
└── vite.config.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

[*.{yml,yaml}]
indent_size = 2

[docker-compose.yml]
indent_size = 4


================================================
FILE: .gitattributes
================================================
* text=auto eol=lf

*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php

/.github export-ignore
CHANGELOG.md export-ignore
.styleci.yml export-ignore


================================================
FILE: .github/FUNDING.yml
================================================
github: solidtime-io


================================================
FILE: .github/ISSUE_TEMPLATE/1_bug_report.yml
================================================
name: Bug Report
description: "Report a bug"
body:
  - type: markdown
    attributes:
      value: |
        Before creating a new bug report, please check that there isn't already a similar issue.

  - type: textarea
    attributes:
      label: Description
      description: A clear and concise description of what the bug is.
    validations:
      required: true

  - type: textarea
    attributes:
      label: "Steps To Reproduce"
      description: How do you trigger this bug? Please walk us through it step by step.
      value: |
        1.
        2.
        3.
        ...
    validations:
      required: false

  - type: dropdown
    attributes:
      label: "Self-hosted or Cloud?"
      options:
        - Self-Hosted
        - solidtime Cloud
        - Both

  - type: input
    attributes:
      label: "Version of solidtime: (for self-hosted)"
    validations:
      required: false

  - type: input
    attributes:
      label: "solidtime self-hosting guide: (for self-hosted)"
      description: "Did you use the official guide to self-host solidtime? If yes, which one?"
    validations:
      required: false


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  - name: 🚀 Feature Request
    url: https://github.com/solidtime-io/solidtime/discussions/new?category=feature-requests
    about: Share ideas for new features
  - name: ❓ Ask a Question
    url: https://github.com/solidtime-io/solidtime/discussions/new?category=general
    about: Ask the community for help


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
## What does this PR do?

<!-- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. -->

- Fixes #XXXX (GitHub issue number)

## Checklist (DO NOT REMOVE)

- [ ] I read the [contributing guide](https://github.com/solidtime-io/solidtime/blob/main/CONTRIBUTING.md)
- [ ] I signed the [Contributor License Agreement](https://cla-assistant.io/solidtime-io/solidtime).
- [ ] I commented my code, particularly in hard-to-understand areas


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "daily"
    target-branch: "main"
  - package-ecosystem: "docker"
    directory: "/"
    schedule:
      interval: "daily"
    target-branch: "main"
  - package-ecosystem: "composer"
    directory: "/"
    schedule:
      interval: "weekly"
    target-branch: "main"
    groups:
      major-updates:
        update-types:
          - "major"
      minor-updates:
        update-types:
          - "minor"
          - "patch"
      security-updates:
        applies-to: version-updates
        update-types:
          - "minor"
          - "patch"
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    target-branch: "main"
    groups:
      major-updates:
        update-types:
          - "major"
      minor-updates:
        update-types:
          - "minor"
          - "patch"
      security-updates:
        applies-to: version-updates
        update-types:
          - "minor"
          - "patch"


================================================
FILE: .github/workflows/build-onpremise.yml
================================================
on:
  push:
    branches:
      - main
      - develop
    tags:
      - '*'
  pull_request:
    paths:
      - '.github/workflows/build-onpremise.yml'
      - 'docker/prod/**'
  workflow_dispatch:

permissions:
  packages: write
  contents: read
  attestations: write
  id-token: write

env:
  DOCKER_REPO: registry.on-premise.solidtime.io/solidtime/solidtime

name: Build - On Premise
jobs:
  build:
    strategy:
      matrix:
        include:
          - runs-on: "ubuntu-24.04-arm"
            platform: "linux/arm64"
          - runs-on: "ubuntu-24.04"
            platform: "linux/amd64"
    runs-on: ${{ matrix.runs-on }}
    timeout-minutes: 90

    steps:
      - name: "Check out code"
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # Required for WyriHaximus/github-action-get-previous-tag

      - name: "Get build"
        id: release-build
        run: echo "build=$(git rev-parse --short=8 HEAD)" >> "$GITHUB_OUTPUT"

      - name: "Get Previous tag (normal push)"
        id: previoustag
        if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
        uses: "WyriHaximus/github-action-get-previous-tag@v1"
        with:
          prefix: "v"

      - name: "Get version"
        id: release-version
        run: |
          if ${{ !startsWith(github.ref, 'refs/tags/v') }}; then
            if ${{ startsWith(steps.previoustag.outputs.tag, 'v') }}; then
              version=$(echo "${{ steps.previoustag.outputs.tag }}" | cut -c 2-)
              echo "app_version=${version}" >> "$GITHUB_OUTPUT"
            else
              echo "ERROR: No previous tag found";
              exit 1;
            fi
          else
            version=$(echo "${{ github.ref }}" | cut -c 12-)
            echo "app_version=${version}" >> "$GITHUB_OUTPUT"
          fi

      - name: "Copy .env template for production"
        run: |
          cp .env.production .env
          rm .env.production .env.ci .env.example

      - name: "Add version to .env"
        run: sed -i 's/APP_VERSION=0.0.0/APP_VERSION=${{ steps.release-version.outputs.app_version }}/g' .env

      - name: "Add build to .env"
        run: sed -i 's/APP_BUILD=0/APP_BUILD=${{ steps.release-build.outputs.build }}/g' .env

      - name: "Output .env"
        run: cat .env

      - name: "Setup PHP with PECL extension"
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          extensions: mbstring, dom, fileinfo, pgsql

      - name: "Install dependencies"
        run: composer install --no-dev --no-ansi --no-interaction --prefer-dist --ignore-platform-reqs --classmap-authoritative
        if: steps.cache-vendor.outputs.cache-hit != 'true' # Skip if cache hit

      - name: "Use Node.js"
        uses: actions/setup-node@v4
        with:
          node-version: '20.x'

      - name: "Checkout invoicing extension"
        uses: actions/checkout@v4
        with:
          repository: solidtime-io/extension-invoicing
          path: extensions/Invoicing
          ssh-key: ${{ secrets.SSH_PRIVATE_KEY_INVOICING_EXTENSION }}

      - name: "Install composer dependencies in invoicing extension"
        run: cd extensions/Invoicing && composer install --no-dev --no-ansi --no-interaction --prefer-dist --ignore-platform-reqs --classmap-authoritative

      - name: "Install npm dependencies in invoicing extension"
        run: cd extensions/Invoicing && npm ci

      - name: "Activate invoicing extension"
        run: php artisan module:enable Invoicing

      - name: "Install npm dependencies"
        run: npm ci

      - name: "Build"
        run: npm run build

      - name: "Prepare"
        run: |
          platform=${{ matrix.platform }}
          echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV

      - name: "Docker meta"
        id: "meta"
        uses: docker/metadata-action@v5
        with:
          images: |
            ${{ env.DOCKER_REPO }}

      - name: "Login to solidtime OnPremise Registry"
        uses: docker/login-action@v3
        with:
          registry: registry.on-premise.solidtime.io
          username: ${{ secrets.ONPREMISE_USERNAME }}
          password: ${{ secrets.ONPREMISE_TOKEN }}

      - name: "Set up QEMU"
        uses: docker/setup-qemu-action@v3

      - name: "Set up Docker Buildx"
        uses: docker/setup-buildx-action@v3

      - name: "Build and push by digest"
        id: build
        uses: docker/build-push-action@v6
        with:
          context: .
          file: docker/prod/Dockerfile
          build-args: |
            DOCKER_FILES_BASE_PATH=docker/prod/
          platforms: ${{ matrix.platform }}
          labels: ${{ steps.meta.outputs.labels }}
          outputs: type=image,"name=${{ env.DOCKER_REPO }}",push-by-digest=true,name-canonical=true,push=true
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: "Export digest"
        run: |
          mkdir -p ${{ runner.temp }}/digests
          digest="${{ steps.build.outputs.digest }}"
          touch "${{ runner.temp }}/digests/${digest#sha256:}"

      - name: "Upload digest"
        uses: actions/upload-artifact@v4
        with:
          name: digests-${{ env.PLATFORM_PAIR }}
          path: ${{ runner.temp }}/digests/*
          if-no-files-found: error
          retention-days: 1

  merge:
    runs-on: ubuntu-latest
    timeout-minutes: 90
    needs:
      - build
    steps:
      - name: "Download digests"
        uses: actions/download-artifact@v4
        with:
          path: ${{ runner.temp }}/digests
          pattern: digests-*
          merge-multiple: true

      - name: "Login to solidtime OnPremise Registry"
        uses: docker/login-action@v3
        with:
          registry: registry.on-premise.solidtime.io
          username: ${{ secrets.ONPREMISE_USERNAME }}
          password: ${{ secrets.ONPREMISE_TOKEN }}

      - name: "Set up Docker Buildx"
        uses: docker/setup-buildx-action@v3

      - name: "Docker meta"
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: |
            ${{ env.DOCKER_REPO }}
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}

      - name: "Create manifest list and push"
        working-directory: ${{ runner.temp }}/digests
        run: |
          docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
            $(printf '${{ env.DOCKER_REPO }}@sha256:%s ' *)

      - name: "Inspect image"
        run: |
          docker buildx imagetools inspect ${{ env.DOCKER_REPO }}:${{ steps.meta.outputs.version }}


================================================
FILE: .github/workflows/build-private.yml
================================================
on:
  push:
    branches:
      - main
      - develop
    tags:
      - '*'
  pull_request:
    paths:
      - '.github/workflows/build-private.yml'
      - 'docker/prod/**'
  workflow_dispatch:
permissions:
  contents: read

name: Build - Private
jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 20


    steps:
      - name: "Check out code"
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # Required for WyriHaximus/github-action-get-previous-tag

      - name: "Get build"
        id: build
        run: echo "build=$(git rev-parse --short=8 HEAD)" >> "$GITHUB_OUTPUT"

      - name: "Get Previous tag (normal push)"
        id: previoustag
        if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
        uses: "WyriHaximus/github-action-get-previous-tag@v1"
        with:
          prefix: "v"

      - name: "Get version"
        id: version
        run: |
          if ${{ !startsWith(github.ref, 'refs/tags/v') }}; then
            if ${{ startsWith(steps.previoustag.outputs.tag, 'v') }}; then
              version=$(echo "${{ steps.previoustag.outputs.tag }}" | cut -c 2-)
              echo "app_version=${version}" >> "$GITHUB_OUTPUT"
            else
              echo "ERROR: No previous tag found";
              exit 1;
            fi
          else
            version=$(echo "${{ github.ref }}" | cut -c 12-)
            echo "app_version=${version}" >> "$GITHUB_OUTPUT"
          fi

      - name: "Copy .env template for production"
        run: |
          cp .env.production .env
          rm .env.production .env.ci .env.example

      - name: "Add version to .env"
        run: sed -i 's/APP_VERSION=0.0.0/APP_VERSION=${{ steps.version.outputs.app_version }}/g' .env

      - name: "Add build to .env"
        run: sed -i 's/APP_BUILD=0/APP_BUILD=${{ steps.build.outputs.build }}/g' .env

      - name: "Output .env"
        run: cat .env

      - name: "Use Node.js"
        uses: actions/setup-node@v4
        with:
          node-version: '20.x'

      - name: "Checkout billing extension"
        uses: actions/checkout@v4
        with:
          repository: solidtime-io/extension-billing
          path: extensions/Billing
          ssh-key: ${{ secrets.SSH_PRIVATE_KEY_BILLING_EXTENSION }}

      - name: "Install dependencies in billing extension"
        uses: php-actions/composer@v6
        env:
          COMPOSER_AUTH: '{"http-basic": {"spark.laravel.com": {"username": "gregor@vostrak.at", "password": "${{ secrets.LARAVEL_SPARK_API_KEY }}"}}}'
        with:
          working_dir: "extensions/Billing"
          command: install
          only_args: --no-dev --no-ansi --no-interaction --prefer-dist --ignore-platform-reqs --classmap-authoritative
          php_version: 8.3

      - name: "Install npm dependencies in billing extension"
        run: cd extensions/Billing && npm ci

      - name: "Checkout services extension"
        uses: actions/checkout@v4
        with:
          repository: solidtime-io/extension-services
          path: extensions/Services
          ssh-key: ${{ secrets.SSH_PRIVATE_KEY_SERVICES_EXTENSION }}

      - name: "Install composer dependencies in services extension"
        uses: php-actions/composer@v6
        with:
          working_dir: "extensions/Services"
          command: install
          only_args: --no-dev --no-ansi --no-interaction --prefer-dist --ignore-platform-reqs --classmap-authoritative
          php_version: 8.3

      - name: "Install npm dependencies in services extension"
        run: cd extensions/Services && npm ci

      - name: "Checkout invoicing extension"
        uses: actions/checkout@v4
        with:
          repository: solidtime-io/extension-invoicing
          path: extensions/Invoicing
          ssh-key: ${{ secrets.SSH_PRIVATE_KEY_INVOICING_EXTENSION }}

      - name: "Install composer dependencies in invoicing extension"
        uses: php-actions/composer@v6
        with:
          working_dir: "extensions/Invoicing"
          command: install
          only_args: --no-dev --no-ansi --no-interaction --prefer-dist --ignore-platform-reqs --classmap-authoritative
          php_version: 8.3

      - name: "Install npm dependencies in invoicing extension"
        run: cd extensions/Invoicing && npm ci

      - name: "Setup PHP with PECL extension"
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          extensions: mbstring, dom, fileinfo, pgsql

      - name: "Install dependencies"
        uses: php-actions/composer@v6
        if: steps.cache-vendor.outputs.cache-hit != 'true' # Skip if cache hit
        with:
          command: install
          only_args: --no-dev --no-ansi --no-interaction --prefer-dist --ignore-platform-reqs --classmap-authoritative
          php_version: 8.3

      - name: "Activate billing extension"
        run: php artisan module:enable Billing

      - name: "Activate services extension"
        run: php artisan module:enable Services

      - name: "Activate invoicing extension"
        run: php artisan module:enable Invoicing

      - name: "Install npm dependencies"
        run: npm ci

      - name: "Build"
        run: npm run build
        env:
          SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}

      - name: "Login to GitHub Container Registry"
        uses: docker/login-action@v3
        with:
          registry: rg.fr-par.scw.cloud/solidtime
          username: nologin
          password: ${{ secrets.SCALEWAY_REGISTRY_TOKEN }}

      - name: "Docker meta"
        id: "meta"
        uses: docker/metadata-action@v5
        with:
          images: rg.fr-par.scw.cloud/solidtime/solidtime
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=sha,format=long

      - name: "Set up QEMU"
        uses: docker/setup-qemu-action@v3

      - name: "Set up Docker Buildx"
        uses: docker/setup-buildx-action@v3

      - name: "Build and push"
        uses: docker/build-push-action@v6
        with:
          context: .
          build-args: |
            DOCKER_FILES_BASE_PATH=docker/prod/
          file: docker/prod/Dockerfile
          push: true
          platforms: linux/amd64
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max


================================================
FILE: .github/workflows/build-public.yml
================================================
on:
  push:
    branches:
      - main
      - develop
    tags:
      - '*'
  pull_request:
    paths:
      - '.github/workflows/build-public.yml'
      - 'docker/prod/**'
  workflow_dispatch:

permissions:
  packages: write
  contents: read
  attestations: write
  id-token: write

env:
  DOCKERHUB_REPO: solidtime/solidtime
  GHCR_REPO: ghcr.io/solidtime-io/solidtime

name: Build - Public
jobs:
  build:
    strategy:
      matrix:
        include:
          - runs-on: "ubuntu-24.04-arm"
            platform: "linux/arm64"
          - runs-on: "ubuntu-24.04"
            platform: "linux/amd64"
    runs-on: ${{ matrix.runs-on }}
    timeout-minutes: 90

    steps:
      - name: "Check out code"
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # Required for WyriHaximus/github-action-get-previous-tag

      - name: "Get build"
        id: release-build
        run: echo "build=$(git rev-parse --short=8 HEAD)" >> "$GITHUB_OUTPUT"

      - name: "Get Previous tag (normal push)"
        id: previoustag
        if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
        uses: "WyriHaximus/github-action-get-previous-tag@v1"
        with:
          prefix: "v"

      - name: "Get version"
        id: release-version
        run: |
          if ${{ !startsWith(github.ref, 'refs/tags/v') }}; then
            if ${{ startsWith(steps.previoustag.outputs.tag, 'v') }}; then
              version=$(echo "${{ steps.previoustag.outputs.tag }}" | cut -c 2-)
              echo "app_version=${version}" >> "$GITHUB_OUTPUT"
            else
              echo "ERROR: No previous tag found";
              exit 1;
            fi
          else
            version=$(echo "${{ github.ref }}" | cut -c 12-)
            echo "app_version=${version}" >> "$GITHUB_OUTPUT"
          fi

      - name: "Copy .env template for production"
        run: |
          cp .env.production .env
          rm .env.production .env.ci .env.example

      - name: "Add version to .env"
        run: sed -i 's/APP_VERSION=0.0.0/APP_VERSION=${{ steps.release-version.outputs.app_version }}/g' .env

      - name: "Add build to .env"
        run: sed -i 's/APP_BUILD=0/APP_BUILD=${{ steps.release-build.outputs.build }}/g' .env

      - name: "Output .env"
        run: cat .env

      - name: "Setup PHP with PECL extension"
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          extensions: mbstring, dom, fileinfo, pgsql

      - name: "Install dependencies"
        run: composer install --no-dev --no-ansi --no-interaction --prefer-dist --ignore-platform-reqs --classmap-authoritative
        if: steps.cache-vendor.outputs.cache-hit != 'true' # Skip if cache hit

      - name: "Use Node.js"
        uses: actions/setup-node@v4
        with:
          node-version: '20.x'

      - name: "Install npm dependencies"
        run: npm ci

      - name: "Build"
        run: npm run build

      - name: "Prepare"
        run: |
          platform=${{ matrix.platform }}
          echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV

      - name: "Docker meta"
        id: "meta"
        uses: docker/metadata-action@v5
        with:
          images: |
            ${{ env.DOCKERHUB_REPO }}
            ${{ env.GHCR_REPO }}

      - name: "Login to Docker Hub Container Registry"
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: "Login to GitHub Container Registry"
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: "Set up QEMU"
        uses: docker/setup-qemu-action@v3

      - name: "Set up Docker Buildx"
        uses: docker/setup-buildx-action@v3

      - name: "Build and push by digest"
        id: build
        uses: docker/build-push-action@v6
        with:
          context: .
          file: docker/prod/Dockerfile
          build-args: |
            DOCKER_FILES_BASE_PATH=docker/prod/
          platforms: ${{ matrix.platform }}
          labels: ${{ steps.meta.outputs.labels }}
          outputs: type=image,"name=${{ env.DOCKERHUB_REPO }},${{ env.GHCR_REPO }}",push-by-digest=true,name-canonical=true,push=true
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: "Export digest"
        run: |
          mkdir -p ${{ runner.temp }}/digests
          digest="${{ steps.build.outputs.digest }}"
          touch "${{ runner.temp }}/digests/${digest#sha256:}"

      - name: "Upload digest"
        uses: actions/upload-artifact@v4
        with:
          name: digests-${{ env.PLATFORM_PAIR }}
          path: ${{ runner.temp }}/digests/*
          if-no-files-found: error
          retention-days: 1

  merge:
    runs-on: ubuntu-latest
    timeout-minutes: 90
    needs:
      - build
    steps:
      - name: "Download digests"
        uses: actions/download-artifact@v4
        with:
          path: ${{ runner.temp }}/digests
          pattern: digests-*
          merge-multiple: true

      - name: "Login to Docker Hub"
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: "Login to GHCR"
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: "Set up Docker Buildx"
        uses: docker/setup-buildx-action@v3

      - name: "Docker meta"
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: |
            ${{ env.DOCKERHUB_REPO }}
            ${{ env.GHCR_REPO }}
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}

      - name: "Create manifest list and push"
        working-directory: ${{ runner.temp }}/digests
        run: |
          docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
            $(printf '${{ env.DOCKERHUB_REPO }}@sha256:%s ' *)
          docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
            $(printf '${{ env.GHCR_REPO }}@sha256:%s ' *)

      - name: "Inspect image"
        run: |
          docker buildx imagetools inspect ${{ env.DOCKERHUB_REPO }}:${{ steps.meta.outputs.version }}
          docker buildx imagetools inspect ${{ env.GHCR_REPO }}:${{ steps.meta.outputs.version }}


================================================
FILE: .github/workflows/generate-api-docs.yml
================================================
name: Generate API docs
on:
  push:
    branches:
      - main
permissions:
  contents: read

jobs:
  api_docs:
    runs-on: ubuntu-latest
    timeout-minutes: 10

    services:
      pgsql_test:
        image: postgres:15
        env:
          PGPASSWORD: 'root'
          POSTGRES_DB: 'laravel'
          POSTGRES_USER: 'root'
          POSTGRES_PASSWORD: 'root'
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - name: "Checkout code"
        uses: actions/checkout@v4

      - name: "Setup PHP"
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv

      - name: "Run composer install"
        run: composer install -n --prefer-dist

      - name: "Create build directory"
        run: mkdir build

      - name: Prepare Laravel Application
        run: |
          cp .env.ci .env
          php artisan migrate

      - name: "Export API docs"
        run: php artisan scramble:export --path=build/api-docs.json

      - name: "Upload API docs to GitHub"
        uses: actions/upload-artifact@v4
        with:
          name: api-docs.json
          path: build/api-docs.json

      - name: "Download Fastfront CLI"
        run: curl https://fastfront-cli.s3.fr-par.scw.cloud/fastfront-cli.phar -o fastfront-cli.phar

      - name: "Deploy with Fastfront"
        run: php fastfront-cli.phar deploy 9beab6cf-f459-446b-85f1-38ec007cf457 ./build
        env:
          FASTFRONT_API_KEY: ${{ secrets.FASTFRONT_API_DOCS_API_KEY }}


================================================
FILE: .github/workflows/npm-build.yml
================================================
name: NPM Build

on: [push]
permissions:
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
      - name: "Checkout code"
        uses: actions/checkout@v4

      - name: "Setup PHP (for Ziggy)"
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          extensions: intl, zip
          coverage: none

      - name: "Run composer install (for Ziggy)"
        run: composer install -n --prefer-dist

      - name: "Use Node.js"
        uses: actions/setup-node@v4
        with:
          node-version: '20.x'

      - name: "Install npm dependencies"
        run: npm ci

      - name: "Build"
        run: npm run build


================================================
FILE: .github/workflows/npm-format-check.yml
================================================
name: NPM Format Check

on: [push]

jobs:
  format-check:
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
      - name: "Checkout code"
        uses: actions/checkout@v4

      - name: "Use Node.js"
        uses: actions/setup-node@v4
        with:
          node-version: '20.x'

      - name: "Install npm dependencies"
        run: npm ci

      - name: "Check code formatting"
        run: npm run format:check 

================================================
FILE: .github/workflows/npm-lint.yml
================================================
name: NPM Lint

on: [push]
permissions:
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
      - name: "Checkout code"
        uses: actions/checkout@v4

      - name: "Use Node.js"
        uses: actions/setup-node@v4
        with:
          node-version: '20.x'

      - name: "Install npm dependencies"
        run: npm ci

      - name: "Run linter"
        run: npm run lint


================================================
FILE: .github/workflows/npm-publish-api.yml
================================================
name: Publish API package to NPM
on:
  workflow_dispatch
permissions:
  contents: read
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
    steps:
      - name: "Checkout code"
        uses: actions/checkout@v4
      # Setup .npmrc file to publish to npm
      - name: Install root project dependencies
        run: npm ci
      - uses: actions/setup-node@v4
        with:
          node-version: '20.x'
          registry-url: 'https://registry.npmjs.org'
      - name: Install dependencies
        run: npm ci
        working-directory: ./resources/js/packages/api
      - name: Build package
        run: npm run build
        working-directory: ./resources/js/packages/api
      - name: Publish Package
        run: npm publish --provenance --access public
        working-directory: ./resources/js/packages/api
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}


================================================
FILE: .github/workflows/npm-publish-ui.yml
================================================
name: Publish UI package to NPM
on:
  workflow_dispatch
permissions:
  contents: read
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
    steps:
      - name: "Checkout code"
        uses: actions/checkout@v4
      # Setup .npmrc file to publish to npm
      - uses: actions/setup-node@v4
        with:
          node-version: '20.x'
          registry-url: 'https://registry.npmjs.org'
      - name: Install root project dependencies
        run: npm ci
      - name: Install package dependencies
        run: npm ci
        working-directory: ./resources/js/packages/ui
      - name: Build package
        run: npm run build
        working-directory: ./resources/js/packages/ui
      - name: Publish Package
        run: npm publish --provenance --access public
        working-directory: ./resources/js/packages/ui
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}


================================================
FILE: .github/workflows/npm-typecheck.yml
================================================
name: NPM Typecheck

on: [push]
permissions:
  contents: read
jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
      - name: "Checkout code"
        uses: actions/checkout@v4

      - name: "Setup PHP (for Ziggy)"
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          extensions: intl, zip
          coverage: none

      - name: "Run composer install (for Ziggy)"
        run: composer install -n --prefer-dist

      - name: "Use Node.js"
        uses: actions/setup-node@v4
        with:
          node-version: '20.x'

      - name: "Install npm dependencies"
        run: npm ci

      - name: "Run type check"
        run: npm run type-check


================================================
FILE: .github/workflows/phpstan.yml
================================================
name: Static code analysis (PHPStan)
on: push
permissions:
  contents: read
jobs:
  phpstan:
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
      - name: "Checkout code"
        uses: actions/checkout@v4

      - name: "Setup PHP"
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv
          coverage: none

      - name: "Run composer install"
        run: composer install -n --prefer-dist

      - name: "Run PHPStan"
        run: composer analyse




================================================
FILE: .github/workflows/phpunit.yml
================================================
name: PHPUnit Tests
on: push
permissions:
  contents: read
jobs:
  phpunit:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    strategy:
      matrix:
        postgres_version: [ 15, 16, 17 ]

    services:
      pgsql_test:
        image: postgres:${{ matrix.postgres_version }}
        env:
          PGPASSWORD: 'root'
          POSTGRES_DB: 'laravel'
          POSTGRES_USER: 'root'
          POSTGRES_PASSWORD: 'root'
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
      gotenberg:
        image: gotenberg/gotenberg:8
        ports:
          - 3000:3000
        options: >-
          --health-cmd "curl --silent --fail http://localhost:3000/health"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    steps:
      - name: "Checkout code"
        uses: actions/checkout@v4

      - name: "Setup PHP"
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv
          coverage: pcov

      - name: "Run composer install"
        run: composer install -n --prefer-dist

      - uses: actions/setup-node@v4
        with:
          node-version: '20.x'

      - name: "Install dependencies"
        run: npm ci

      - name: "Build Frontend"
        run: npm run build

      - name: "Prepare Laravel Application"
        run: |
          cp .env.ci .env
          php artisan key:generate
          php artisan passport:keys

      - name: "Run PHPUnit"
        run: php artisan test --stop-on-failure --coverage-text --coverage-clover=coverage.xml

      - name: "Upload coverage reports to Codecov"
        uses: codecov/codecov-action@v5.4.3
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          slug: solidtime-io/solidtime


================================================
FILE: .github/workflows/pint.yml
================================================
name: PHP Linting
on: push
permissions:
  contents: read
jobs:
  pint:
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
      - name: "Checkout code"
        uses: actions/checkout@v4

      - name: "Check code style"
        uses: aglipanci/laravel-pint-action@2.5
        with:
          configPath: "pint.json"


================================================
FILE: .github/workflows/playwright.yml
================================================
name: Playwright Tests
on: [push]
permissions:
  contents: read
jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 60
    strategy:
      fail-fast: false
      matrix:
        shardIndex: [1, 2, 3, 4, 5, 6, 7, 8]
        shardTotal: [8]

    services:
      mailpit:
        image: 'axllent/mailpit:latest'
        ports:
          - 1025:1025
          - 8025:8025
      pgsql_test:
        image: postgres:15
        env:
          PGPASSWORD: 'root'
          POSTGRES_DB: 'laravel'
          POSTGRES_USER: 'root'
          POSTGRES_PASSWORD: 'root'
        ports:
          - 5432:5432
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - name: "Checkout code"
        uses: actions/checkout@v4

      - name: "Setup node"
        uses: actions/setup-node@v4
        with:
          node-version: '20.x'

      - name: "Setup PHP"
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv
          coverage: none

      - name: "Run composer install"
        run: composer install -n --prefer-dist

      - name: "Prepare Laravel Application"
        run: |
          cp .env.ci .env
          php artisan key:generate
          php artisan passport:keys
          php artisan migrate --seed

      - name: "Install dependencies"
        run: npm ci

      - name: "Build Frontend"
        run: npm run build

      - name: "Install FrankenPHP"
        run: |
          ARCH="$(uname -m)"
          curl -fsSL "https://github.com/dunglas/frankenphp/releases/latest/download/frankenphp-linux-${ARCH}" -o /usr/local/bin/frankenphp
          chmod +x /usr/local/bin/frankenphp

      - name: "Run Laravel Octane Server"
        run: php artisan octane:start --server=frankenphp --host=127.0.0.1 --port=8000 --workers=4 --max-requests=500 > /dev/null 2>&1 &
        env:
          OCTANE_SERVER: frankenphp

      - name: "Install Playwright Browsers"
        run: npx playwright install --with-deps

      - name: "Run Playwright tests"
        run: npx playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
        env:
          PLAYWRIGHT_BASE_URL: 'http://127.0.0.1:8000'
          MAILPIT_BASE_URL: 'http://localhost:8025'

      - name: "Upload blob report"
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: blob-report-${{ matrix.shardIndex }}
          path: blob-report/
          retention-days: 7

  merge-reports:
    if: always()
    needs: [test]
    runs-on: ubuntu-latest
    steps:
      - name: "Checkout code"
        uses: actions/checkout@v4

      - name: "Setup node"
        uses: actions/setup-node@v4
        with:
          node-version: '20.x'

      - name: "Install dependencies"
        run: npm ci

      - name: "Download blob reports"
        uses: actions/download-artifact@v4
        with:
          path: all-blob-reports
          pattern: blob-report-*
          merge-multiple: true

      - name: "Merge reports"
        run: npx playwright merge-reports --reporter html ./all-blob-reports

      - name: "Upload merged HTML report"
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 30


================================================
FILE: .gitignore
================================================
/.phpunit.cache
node_modules
dist
/public/build
/public/hot
/public/storage
/public/css
/public/js
/public/vendor
/lang/vendor
/storage/*.key
/vendor
.env
.env.backup
.phpunit.result.cache
Homestead.json
Homestead.yaml
auth.json
npm-debug.log
yarn-error.log
/.fleet
/.idea
/.vscode
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/coverage
/extensions
!/extensions/.gitkeep
!/extensions/extensions_autoload.php
/auth.json
/modules_statuses.json
/k8s
/_ide_helper.php
/.phpstorm.meta.php
/.rnd

/caddy
/frankenphp
/public/frankenphp-worker.php
/data
/config/caddy
/config/composer


================================================
FILE: .prettierignore
================================================
# Ignore build outputs
node_modules/
vendor/
storage/
bootstrap/cache/
public/build/
public/hot/

# Ignore lock files
package-lock.json
composer.lock

# Ignore generated files
*.min.js
*.min.css

# Ignore test results
test-results/
playwright-report/

# Ignore IDE files
.idea/
.vscode/

# Ignore OS files
.DS_Store
Thumbs.db 

================================================
FILE: .prettierrc.json
================================================
{
    "trailingComma": "es5",
    "tabWidth": 4,
    "singleQuote": true,
    "bracketSameLine": true,
    "quoteProps": "preserve",
    "printWidth": 100
}


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Code of Conduct

The goal is to create a community that is open and welcoming to all individuals.
To achieve this, we have developed a code of conduct that outlines the expectations for behavior of all members of our community.

## Pledge

This community is founded on respect and understanding.
All members are expected to treat others with respect and empathy, and to not tolerate any form of discrimination,
harassment, or attacks.

## Expectations

Examples of behavior that contributes to creating a positive environment include:

- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

- The use of sexualized language or imagery and sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting

## Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate
and fair corrective action in response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits,
issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily
or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

## Contact

If you feel uncomfortable or believe that someone has violated the code of conduct, please contact us at [hello@solidtime.io](mailto:hello@solidtime.io).
We will thoroughly investigate the incident and aim for the best possible outcome.


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to solidtime

Contributions are greatly apprecited, please make sure to read the rules and vision for solidtime before contributing. 

## Rules

### Issues for Bugs, Discussions for Feature requests

In order to keep the issues of the repository clean we decided to only use them for bugs. Feature Requests and enhancement are handled in discussions. This also helps us to see which feature requests are popular as they can be upvoted. 

### Only work on approved issues

To respect your time and help us manage contributions effectively, please open an issue or start a discussion and wait for approval before submitting a pull request (PR). This does not apply to tiny fixes or changes however, please keep in mind that we might not merge PRs for various reasons. 

### Contributor License Agreement

You'll also notice that we’ve set up a [Contributor License Agreement (CLA)](https://cla-assistant.io/solidtime-io/solidtime), which must be signed before any PR can be merged. Don’t worry - the process is quick and only takes a few clicks.

We want to be transparent about why we require the CLA and what it means for your contributions and the codebase. That’s why we’ve written a few paragraphs below outlining our plans and vision for solidtime in the **Vision** part of this document. 

### Prevent Duplicate Work

Before you submit a new PR, make sure that none exists already. If you plan to work on an issue, make sure to let us and others know by commenting on the issue/discussion. 

### Give context

Tell us what you thinking was behind the decisions you made while drafting the PR. Treat the PR itself as documentation for everyone who wants to go back and understand why certain decisions were made. 

### Summarize your PR

Please make sure to include a short summary at the top of your PR to make it easy for us to quickly check what the PR is about, without looking at the code changes. 

### Use Github Keywords and Auto-Link Issues

Use phrases like "Closes #123" or "Fixes #123" in the PR description to link the PR with the issue that you are adressing. 

### Mention what you tested and how

Explain how you tested and validated the implementation. 

### Keep Naming consistent

Look at existing code patterns and use naming conventions that already exist in the code base. 

### Testing

We have an exhaustive test-suite of PHPUnit (Backend) and Playwright (Frontend) testing. Whereever applicable please make sure to write add tests to the codebase. 

### Linting & Formatting

Make sure to run linting and formatting commands before you commit the changes. 

For backend changes:

```
composer fix
composer analyse
```

For frontend changes: 

```
npm run lint:fix
npm run format
```

## Vision

We started solidtime to provide an open infrastructure solution for time tracking—one that empowers teams and individuals to fully own their data, instead of depending on proprietary platforms. We believe infrastructure software should be open, accessible, and built to last. However, competing with established market leaders in this space requires long-term financial sustainability.

solidtime is licensed under the AGPL, which we believe is the best available license to strike a balance between openness and financial viability. The AGPL gives us, as the copyright holders, certain exclusive rights that we plan to leverage to fund development. To ensure we retain those rights across the entire codebase, we've put a CLA in place that contributors must sign before submitting code.

One of solidtime’s key advantages is that it's built to be self-hostable. This makes it a great solution for organizations like governments, healthcare providers, and enterprises that are required to keep data on their own infrastructure due to regulations or internal policies. These organizations may need custom licenses, integrations, or modifications that aren't suitable for the open-source version. To support them, we offer relicensed versions of solidtime along with support plans.

We’ll also provide proprietary extensions for solidtime. These will be available to enterprise customers with support plans, but also to individual users or teams who don’t need support, at much more accessible price points. For companies running solidtime on their own infrastructure, this is the easiest way to support the project while gaining additional functionality. While we plan to make it easier to build custom extensions in the future, our current APIs are still highly experimental.

Finally - and perhaps most importantly - we offer a hosted SaaS version called solidtime Cloud, for users who can’t or don’t want to run the software themselves. This version includes proprietary extensions, always runs the latest commit, and includes monitoring and billing features available exclusively on this hosted instance. We expect solidtime Cloud to play a critical role in funding the project long-term.

Having full control over the source code’s licensing also gives us the ability to change the license of the main project in the future. That said, we have no plans to do so and would only consider it in extreme cases - for example, if a malicious actor were to directly compete with our hosted service in a way that threatens the sustainability of the project, the legal interpretation of AGPL changes in a way that would make it unreasonable to use for certain companies, or a new similar license gains wide-spread adoption. Regardless, solidtime will always remain free to self-host for individuals and companies who use it as part of their work, and all previous releases will remain licensed under AGPL.

If you are using the open-source version of solidtime and want to support us, the best way to do so is to spread the word. 


================================================
FILE: LICENSE.md
================================================
GNU Affero General Public License
=================================

_Version 3, 19 November 2007_
_Copyright © 2007 Free Software Foundation, Inc. &lt;<http://fsf.org/>&gt;_

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

## Preamble

The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.

The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.

When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

Developers that use our General Public Licenses protect your rights
with two steps: **(1)** assert copyright on the software, and **(2)** offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.

A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate.  Many developers of free software are heartened and
encouraged by the resulting cooperation.  However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.

The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community.  It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server.  Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.

An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals.  This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.

The precise terms and conditions for copying, distribution and
modification follow.

## TERMS AND CONDITIONS

### 0. Definitions

“This License” refers to version 3 of the GNU Affero General Public License.

“Copyright” also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

“The Program” refers to any copyrightable work licensed under this
License.  Each licensee is addressed as “you”.  “Licensees” and
“recipients” may be individuals or organizations.

To “modify” a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a “modified version” of the
earlier work or a work “based on” the earlier work.

A “covered work” means either the unmodified Program or a work based
on the Program.

To “propagate” a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

To “convey” a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

An interactive user interface displays “Appropriate Legal Notices”
to the extent that it includes a convenient and prominently visible
feature that **(1)** displays an appropriate copyright notice, and **(2)**
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

### 1. Source Code

The “source code” for a work means the preferred form of the work
for making modifications to it.  “Object code” means any non-source
form of a work.

A “Standard Interface” means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

The “System Libraries” of an executable work include anything, other
than the work as a whole, that **(a)** is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and **(b)** serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
“Major Component”, in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

The “Corresponding Source” for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

The Corresponding Source for a work in source code form is that
same work.

### 2. Basic Permissions

All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

### 3. Protecting Users' Legal Rights From Anti-Circumvention Law

No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

### 4. Conveying Verbatim Copies

You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

### 5. Conveying Modified Source Versions

You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

* **a)** The work must carry prominent notices stating that you modified
it, and giving a relevant date.
* **b)** The work must carry prominent notices stating that it is
released under this License and any conditions added under section 7.
This requirement modifies the requirement in section 4 to
“keep intact all notices”.
* **c)** You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy.  This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged.  This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
* **d)** If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.

A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
“aggregate” if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

### 6. Conveying Non-Source Forms

You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

* **a)** Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
* **b)** Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either **(1)** a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or **(2)** access to copy the
Corresponding Source from a network server at no charge.
* **c)** Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source.  This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
* **d)** Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge.  You need not require recipients to copy the
Corresponding Source along with the object code.  If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source.  Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
* **e)** Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.

A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

A “User Product” is either **(1)** a “consumer product”, which means any
tangible personal property which is normally used for personal, family,
or household purposes, or **(2)** anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, “normally used” refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

“Installation Information” for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

### 7. Additional Terms

“Additional permissions” are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

* **a)** Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
* **b)** Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
* **c)** Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
* **d)** Limiting the use for publicity purposes of names of licensors or
authors of the material; or
* **e)** Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
* **f)** Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.

All other non-permissive additional terms are considered “further
restrictions” within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

### 8. Termination

You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated **(a)**
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and **(b)** permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

### 9. Acceptance Not Required for Having Copies

You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

### 10. Automatic Licensing of Downstream Recipients

Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

An “entity transaction” is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

### 11. Patents

A “contributor” is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's “contributor version”.

A contributor's “essential patent claims” are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, “control” includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

In the following three paragraphs, a “patent license” is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To “grant” such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either **(1)** cause the Corresponding Source to be so
available, or **(2)** arrange to deprive yourself of the benefit of the
patent license for this particular work, or **(3)** arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  “Knowingly relying” means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

A patent license is “discriminatory” if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license **(a)** in connection with copies of the covered work
conveyed by you (or copies made from those copies), or **(b)** primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

### 12. No Surrender of Others' Freedom

If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

### 13. Remote Network Interaction; Use with the GNU General Public License

Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software.  This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.

Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.

### 14. Revised Versions of this License

The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time.  Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU Affero General
Public License “or any later version” applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.

If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

### 15. Disclaimer of Warranty

THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

### 16. Limitation of Liability

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

### 17. Interpretation of Sections 15 and 16

If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

_END OF TERMS AND CONDITIONS_

## How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the “copyright” line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) 2024 Gregor Vostrak & Constantin Graf

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source.  For example, if your program is a web application, its
interface could display a “Source” link that leads users to an archive
of the code.  There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.

You should also get your employer (if you work as a programmer) or school,
if any, to sign a “copyright disclaimer” for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
&lt;<http://www.gnu.org/licenses/>&gt;.


================================================
FILE: README.md
================================================
# solidtime - The modern Open-Source Time Tracker

[![GitHub License](https://img.shields.io/github/license/solidtime-io/solidtime?style=flat-square)](https://github.com/solidtime-io/solidtime/blob/main/LICENSE.md)
[![Codecov](https://img.shields.io/codecov/c/github/solidtime-io/solidtime?style=flat-square&logo=codecov)](https://codecov.io/gh/solidtime-io/solidtime)
![GitHub Actions Unit Tests Status](https://img.shields.io/github/actions/workflow/status/solidtime-io/solidtime/phpunit.yml?style=flat-square)
![PHPStan badge](https://img.shields.io/badge/PHPStan-Level_7-blue?style=flat-square&color=blue)

![Screenshot of the solidtime application with header: solidtime - The modern Open-Source Time Tracker](docs/solidtime-banner.png "solidtime Banner")

solidtime is a modern open-source time tracking application for Freelancers and Agencies.

## Features

 - Time tracking: Track your time with a modern and easy-to-use interface
 - Projects: Create and manage projects and assign project members
 - Tasks: Create and manage tasks and assign tasks to projects
 - Clients: Create and manage clients and assign clients to projects
 - Billable rates: Set billable rates for projects, project members, organization members and organizations 
 - Multiple organizations: Create and manage multiple organizations with one account
 - Roles and permissions: Create and manage organizations
 - Import: Import your time tracking data from other time tracking applications (Supported: Toggl, Clockify, Timeentry CSV)

## Self Hosting

If you are looking into self-hosting solidtime, you can find the guides [here](https://docs.solidtime.io/self-hosting/intro)

We also have an examples repository [here](https://github.com/solidtime-io/self-hosting-examples)

If you do not want to self-host solidtime or try it out you can sign up for [solidtime cloud](https://www.solidtime.io/)

## Issues & Feature Requests

If you find any **bugs in solidtime**, please feel free to [**open an issue**](https://github.com/solidtime-io/solidtime/issues/new) in this repository, with instructions on how to reproduce the bug. 
If you have a **feature request**, please [**create a discussion**](https://github.com/solidtime-io/solidtime/discussions/new?category=feature-requests) in this repository.

## Contributing

Please open an issue or start a discussion and wait for approval before submitting a pull request. This does not apply to tiny fixes or changes however, please keep in mind that we might not merge PRs for various reasons. 

**If you submit an AI slop pull request (especially without following the proper procedure), you will be banned from future contributions to solidtime.**

Please read the [CONTRIBUTING.md](./CONTRIBUTING.md) before sumbitting a Pull Request.

We do accept contributions in the [documentation repository](https://github.com/solidtime-io/docs) f.e. to add new self-hosting guides.

## Security

Looking to report a vulnerability? Please refer our [SECURITY.md](./SECURITY.md) file.

## License

This project is open-source and available under the GNU Affero General Public License v3.0 (AGPL v3). Please see the [license file](LICENSE.md) for more information.


================================================
FILE: SECURITY.md
================================================
# Security Policy

## Reporting a Vulnerability

If you discover a security vulnerability regarding this project, please e-mail me to [security@solidtime.io](mailto:security@solidtime.io)!


================================================
FILE: app/Actions/Fortify/CreateNewUser.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Fortify;

use App\Enums\Weekday;
use App\Events\NewsletterRegistered;
use App\Models\User;
use App\Service\IpLookup\IpLookupServiceContract;
use App\Service\TimezoneService;
use App\Service\UserService;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
use Korridor\LaravelModelValidationRules\Rules\UniqueEloquent;
use Laravel\Fortify\Contracts\CreatesNewUsers;
use Laravel\Jetstream\Jetstream;
use Log;

class CreateNewUser implements CreatesNewUsers
{
    use PasswordValidationRules;

    /**
     * Create a newly registered user.
     *
     * @param  array<string, mixed>  $input
     *
     * @throws ValidationException
     */
    public function create(array $input): User
    {
        if (! config('app.enable_registration')) {
            throw ValidationException::withMessages([
                'email' => [__('Registration is disabled.')],
            ]);
        }

        Validator::make($input, [
            'name' => [
                'required',
                'string',
                'max:255',
            ],
            'email' => [
                'required',
                'string',
                'email:rfc,strict',
                'max:255',
                UniqueEloquent::make(User::class, 'email', function (Builder $builder): Builder {
                    /** @var Builder<User> $builder */
                    return $builder->where('is_placeholder', '=', false);
                }),
            ],
            'password' => $this->passwordRules(),
            'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['accepted', 'required'] : '',
            'newsletter_consent' => [
                'boolean',
            ],
        ])->validate();

        $timezone = null;
        if (array_key_exists('timezone', $input) && is_string($input['timezone'])) {
            if (app(TimezoneService::class)->isValid($input['timezone'])) {
                $timezone = $input['timezone'];
            } else {
                $timezone = app(TimezoneService::class)->mapLegacyTimezone($input['timezone']);
                if ($timezone === null) {
                    Log::debug('Invalid timezone', ['timezone' => $input['timezone']]);
                }
            }
        }

        $ipLookupResponse = app(IpLookupServiceContract::class)->lookup(request()->ip());

        $startOfWeek = Weekday::Monday;
        $numberFormat = null;
        $currencyFormat = null;
        $dateFormat = null;
        $intervalFormat = null;
        $timeFormat = null;
        $currency = null;
        if ($ipLookupResponse !== null) {
            $startOfWeek = $ipLookupResponse->startOfWeek ?? Weekday::Monday;
            if ($timezone === null) {
                $timezone = $ipLookupResponse->timezone;
            }
            $currency = $ipLookupResponse->currency;
        }
        $user = null;
        DB::transaction(function () use (&$user, $input, $timezone, $startOfWeek, $currency, $numberFormat, $currencyFormat, $dateFormat, $intervalFormat, $timeFormat): void {
            $userService = app(UserService::class);
            $user = $userService->createUser(
                $input['name'],
                $input['email'],
                $input['password'],
                $timezone ?? 'UTC',
                $startOfWeek,
                $currency,
                $numberFormat,
                $currencyFormat,
                $dateFormat,
                $intervalFormat,
                $timeFormat
            );
        });

        $newsletterConsent = isset($input['newsletter_consent']) && (bool) $input['newsletter_consent'];
        if ($newsletterConsent) {
            NewsletterRegistered::dispatch($input['name'], $input['email'], $user->getKey());
        }

        return $user;
    }
}


================================================
FILE: app/Actions/Fortify/PasswordValidationRules.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Fortify;

use Illuminate\Contracts\Validation\Rule;
use Illuminate\Validation\Rules\Password;

trait PasswordValidationRules
{
    /**
     * Get the validation rules used to validate passwords.
     *
     * @return array<int, Rule|string>
     */
    protected function passwordRules(): array
    {
        return ['required', 'string', Password::default(), 'confirmed'];
    }
}


================================================
FILE: app/Actions/Fortify/ResetUserPassword.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Fortify;

use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Laravel\Fortify\Contracts\ResetsUserPasswords;

class ResetUserPassword implements ResetsUserPasswords
{
    use PasswordValidationRules;

    /**
     * Validate and reset the user's forgotten password.
     *
     * @param  array<string, string>  $input
     */
    public function reset(User $user, array $input): void
    {
        Validator::make($input, [
            'password' => $this->passwordRules(),
        ])->validate();

        $user->forceFill([
            'password' => Hash::make($input['password']),
        ])->save();
    }
}


================================================
FILE: app/Actions/Fortify/UpdateUserPassword.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Fortify;

use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Laravel\Fortify\Contracts\UpdatesUserPasswords;

class UpdateUserPassword implements UpdatesUserPasswords
{
    use PasswordValidationRules;

    /**
     * Validate and update the user's password.
     *
     * @param  array<string, string>  $input
     */
    public function update(User $user, array $input): void
    {
        Validator::make($input, [
            'current_password' => ['required', 'string', 'current_password:web'],
            'password' => $this->passwordRules(),
        ], [
            'current_password.current_password' => __('The provided password does not match your current password.'),
        ])->validateWithBag('updatePassword');

        $user->forceFill([
            'password' => Hash::make($input['password']),
        ])->save();
    }
}


================================================
FILE: app/Actions/Fortify/UpdateUserProfileInformation.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Fortify;

use App\Enums\Weekday;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Korridor\LaravelModelValidationRules\Rules\UniqueEloquent;
use Laravel\Fortify\Contracts\UpdatesUserProfileInformation;

class UpdateUserProfileInformation implements UpdatesUserProfileInformation
{
    /**
     * Validate and update the given user's profile information.
     *
     * @param  array<string, mixed>  $input
     *
     * @throws ValidationException
     */
    public function update(User $user, array $input): void
    {
        Validator::make($input, [
            'name' => [
                'required',
                'string',
                'max:255',
            ],
            'email' => [
                'required',
                'email',
                'max:255',
                UniqueEloquent::make(User::class, 'email')->ignore($user->id)->query(function (Builder $query) {
                    /** @var Builder<User> $query */
                    return $query->where('is_placeholder', '=', false);
                }),
            ],
            'photo' => [
                'nullable',
                'mimes:jpg,jpeg,png',
                'max:1024',
            ],
            'timezone' => [
                'required',
                'timezone:all',
            ],
            'week_start' => [
                'required',
                Rule::enum(Weekday::class),
            ],
        ])->validateWithBag('updateProfileInformation');

        if (isset($input['photo'])) {
            $user->updateProfilePhoto($input['photo']);
        }

        if ($input['email'] !== $user->email) {
            $user->forceFill([
                'name' => $input['name'],
                'email' => $input['email'],
                'email_verified_at' => null,
                'timezone' => $input['timezone'],
                'week_start' => $input['week_start'],
            ])->save();

            $user->sendEmailVerificationNotification();
        } else {
            $user->forceFill([
                'name' => $input['name'],
                'timezone' => $input['timezone'],
                'week_start' => $input['week_start'],
            ])->save();
        }
    }
}


================================================
FILE: app/Actions/Jetstream/AddOrganizationMember.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Jetstream;

use App\Enums\Role;
use App\Models\Organization;
use App\Models\User;
use App\Service\MemberService;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\In;
use Korridor\LaravelModelValidationRules\Rules\ExistsEloquent;
use Laravel\Jetstream\Contracts\AddsTeamMembers;

class AddOrganizationMember implements AddsTeamMembers
{
    /**
     * Add a new team member to the given team.
     */
    public function add(User $owner, Organization $organization, string $email, ?string $role = null): void
    {
        Gate::forUser($owner)->authorize('addTeamMember', $organization); // TODO: refactor after owner refactoring

        $this->validate($organization, $email, $role);

        $newOrganizationMember = User::query()
            ->where('email', $email)
            ->where('is_placeholder', '=', false)
            ->firstOrFail();

        app(MemberService::class)->addMember($newOrganizationMember, $organization, Role::from($role));
    }

    /**
     * Validate the add member operation.
     */
    protected function validate(Organization $organization, string $email, ?string $role): void
    {
        Validator::make([
            'email' => $email,
            'role' => $role,
        ], $this->rules())->after(
            $this->ensureUserIsNotAlreadyOnTeam($organization, $email)
        )->validateWithBag('addTeamMember');
    }

    /**
     * Get the validation rules for adding a team member.
     *
     * @return array<string, array<ValidationRule|Rule|string|In>>
     */
    protected function rules(): array
    {
        return [
            'email' => [
                'required',
                'email',
                ExistsEloquent::make(User::class, 'email', function (Builder $builder) {
                    /** @var Builder<User> $builder */
                    return $builder->where('is_placeholder', '=', false);
                })->withMessage(__('We were unable to find a registered user with this email address.')),
            ],
            'role' => [
                'required',
                'string',
                Rule::in([
                    Role::Admin->value,
                    Role::Manager->value,
                    Role::Employee->value,
                ]),
            ],
        ];
    }

    /**
     * Ensure that the user is not already on the team.
     */
    protected function ensureUserIsNotAlreadyOnTeam(Organization $team, string $email): Closure
    {
        return function ($validator) use ($team, $email): void {
            $validator->errors()->addIf(
                $team->hasRealUserWithEmail($email),
                'email',
                __('This user already belongs to the team.')
            );
        };
    }
}


================================================
FILE: app/Actions/Jetstream/CreateOrganization.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Jetstream;

use App\Events\AfterCreateOrganization;
use App\Models\Organization;
use App\Models\User;
use App\Service\IpLookup\IpLookupServiceContract;
use App\Service\OrganizationService;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
use Laravel\Jetstream\Contracts\CreatesTeams;
use Laravel\Jetstream\Jetstream;

class CreateOrganization implements CreatesTeams
{
    /**
     * Validate and create a new team for the given user.
     *
     * @param  array<string, string>  $input
     *
     * @throws AuthorizationException
     * @throws ValidationException
     */
    public function create(User $user, array $input): Organization
    {
        Gate::forUser($user)->authorize('create', Jetstream::newTeamModel());

        Validator::make($input, [
            'name' => ['required', 'string', 'max:255'],
        ])->validateWithBag('createTeam');

        $ipLookupResponse = app(IpLookupServiceContract::class)->lookup(request()->ip());

        $currency = null;
        if ($ipLookupResponse !== null) {
            $currency = $ipLookupResponse->currency;
        }

        $organization = app(OrganizationService::class)->createOrganization(
            $input['name'],
            $user,
            false,
            $currency
        );

        $user->switchTeam($organization);

        // Note: The refresh is necessary for currently unknown reasons. Do not remove it.
        $organization = $organization->refresh();
        AfterCreateOrganization::dispatch($organization);

        return $organization;
    }
}


================================================
FILE: app/Actions/Jetstream/DeleteOrganization.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Jetstream;

use App\Models\Organization;
use App\Service\DeletionService;
use Laravel\Jetstream\Contracts\DeletesTeams;

class DeleteOrganization implements DeletesTeams
{
    /**
     * Delete the given team.
     */
    public function delete(Organization $organization): void
    {
        /** @see ValidateOrganizationDeletion */
        app(DeletionService::class)->deleteOrganization($organization);
    }
}


================================================
FILE: app/Actions/Jetstream/DeleteUser.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Jetstream;

use App\Exceptions\Api\ApiException;
use App\Models\User;
use App\Service\DeletionService;
use Illuminate\Validation\ValidationException;
use Laravel\Jetstream\Contracts\DeletesUsers;

class DeleteUser implements DeletesUsers
{
    /**
     * Delete the given user.
     *
     * @throws ValidationException
     */
    public function delete(User $user): void
    {
        try {
            app(DeletionService::class)->deleteUser($user);
        } catch (ApiException $exception) {
            throw ValidationException::withMessages([
                'password' => $exception->getTranslatedMessage(),
            ]);
        }
    }
}


================================================
FILE: app/Actions/Jetstream/InviteOrganizationMember.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Jetstream;

use App\Exceptions\MovedToApiException;
use App\Models\Organization;
use App\Models\User;
use Exception;
use Laravel\Jetstream\Contracts\InvitesTeamMembers;

class InviteOrganizationMember implements InvitesTeamMembers
{
    /**
     * Invite a new team member to the given team.
     *
     * @throws Exception
     */
    public function invite(User $user, Organization $organization, string $email, ?string $role = null): void
    {
        throw new MovedToApiException;
    }
}


================================================
FILE: app/Actions/Jetstream/RemoveOrganizationMember.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Jetstream;

use App\Exceptions\MovedToApiException;
use App\Models\Organization;
use App\Models\User;
use Exception;
use Laravel\Jetstream\Contracts\RemovesTeamMembers;

class RemoveOrganizationMember implements RemovesTeamMembers
{
    /**
     * Remove the team member from the given team.
     *
     * @throws Exception
     */
    public function remove(User $user, Organization $organization, User $teamMember): void
    {
        throw new MovedToApiException;
    }
}


================================================
FILE: app/Actions/Jetstream/UpdateMemberRole.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Jetstream;

use App\Enums\Role;
use App\Exceptions\MovedToApiException;
use App\Models\Member;
use App\Models\Organization;
use App\Models\User;
use Exception;

class UpdateMemberRole
{
    /**
     * Update the role for the given team member.
     *
     * @throws Exception
     */
    public function update(User $actingUser, Organization $organization, string $userId, string $role): void
    {
        throw new MovedToApiException;
    }
}


================================================
FILE: app/Actions/Jetstream/UpdateOrganization.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Jetstream;

use App\Models\Organization;
use App\Models\User;
use App\Rules\CurrencyRule;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
use Laravel\Jetstream\Contracts\UpdatesTeamNames;

class UpdateOrganization implements UpdatesTeamNames
{
    /**
     * Validate and update the given team's name.
     *
     * @param  array<string, string>  $input
     *
     * @throws AuthorizationException
     * @throws ValidationException
     */
    public function update(User $user, Organization $organization, array $input): void
    {
        Gate::forUser($user)->authorize('update', $organization);

        Validator::make($input, [
            'name' => [
                'required',
                'string',
                'max:255',
            ],
            'currency' => [
                'required',
                'string',
                new CurrencyRule,
            ],
        ])->validateWithBag('updateTeamName');

        $organization->forceFill([
            'name' => $input['name'],
            'currency' => $input['currency'],
        ])->save();
    }
}


================================================
FILE: app/Actions/Jetstream/ValidateOrganizationDeletion.php
================================================
<?php

declare(strict_types=1);

namespace App\Actions\Jetstream;

use App\Models\Organization;
use App\Models\User;
use App\Service\PermissionStore;
use Illuminate\Auth\Access\AuthorizationException;

class ValidateOrganizationDeletion
{
    /**
     * Validate that the team can be deleted by the given user.
     *
     * @param  User  $user  Authenticated user
     * @param  Organization  $organization  Organization to be deleted
     *
     * @throws AuthorizationException
     */
    public function validate(User $user, Organization $organization): void
    {
        if (! app(PermissionStore::class)->userHas($organization, $user, 'organizations:delete')) {
            throw new AuthorizationException;
        }
    }
}


================================================
FILE: app/Console/Commands/Admin/OrganizationDeleteCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands\Admin;

use App\Models\Organization;
use App\Service\DeletionService;
use Illuminate\Console\Command;
use Illuminate\Support\Str;

class OrganizationDeleteCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'admin:organization:delete
                { organization : The ID of the organization to delete }';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Delete a organization';

    /**
     * Execute the console command.
     */
    public function handle(DeletionService $deletionService): int
    {
        $organizationId = $this->argument('organization');

        if (! Str::isUuid($organizationId)) {
            $this->error('Organization ID must be a valid UUID.');

            return self::FAILURE;

        }

        /** @var Organization|null $organization */
        $organization = Organization::find($organizationId);
        if ($organization === null) {
            $this->error('Organization with ID '.$organizationId.' not found.');

            return self::FAILURE;
        }

        $this->info('Deleting organization with ID '.$organization->getKey());

        $deletionService->deleteOrganization($organization);

        $this->info('Organization with ID '.$organization->getKey().' has been deleted.');

        return self::SUCCESS;
    }
}


================================================
FILE: app/Console/Commands/Admin/UserCreateCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands\Admin;

use App\Enums\Weekday;
use App\Models\Organization;
use App\Models\User;
use App\Service\UserService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use LogicException;

class UserCreateCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'admin:user:create
                { name : The name of the user }
                { email : The email of the user }
                { --ask-for-password : Ask for the password, otherwise the command will generate a random one }
                { --verify-email : Verify the email address of the user }';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Create a new user';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $name = $this->argument('name');
        $email = $this->argument('email');
        $askForPassword = (bool) $this->option('ask-for-password');
        $verifyEmail = (bool) $this->option('verify-email');

        if (User::query()->where('email', $email)->where('is_placeholder', '=', false)->exists()) {
            $this->error('User with email "'.$email.'" already exists.');

            return self::FAILURE;
        }

        if ($askForPassword) {
            $outputPassword = false;
            $password = $this->secret('Enter the password');
        } else {
            $outputPassword = true;
            $password = bin2hex(random_bytes(16));
        }

        $user = null;
        DB::transaction(function () use (&$user, $name, $email, $password, $verifyEmail): void {
            $user = app(UserService::class)->createUser(
                $name,
                $email,
                $password,
                'UTC',
                Weekday::Monday,
                null,
                verifyEmail: $verifyEmail
            );
        });
        /** @var Organization|null $organization */
        $organization = $user->ownedTeams->first();
        if ($organization === null) {
            throw new LogicException('User does not have an organization');
        }

        $this->info('Created user "'.$name.'" ("'.$email.'")');
        $this->line('ID: '.$user->getKey());
        $this->line('Name: '.$name);
        $this->line('Email: '.$email);
        if ($outputPassword) {
            $this->line('Password: '.$password);
        }
        $this->line('Timezone: '.$user->timezone);
        $this->line('Week start: '.$user->week_start->value);

        // Organization
        $this->line('Currency: '.$organization->currency);

        return self::SUCCESS;
    }
}


================================================
FILE: app/Console/Commands/Admin/UserVerifyCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands\Admin;

use App\Models\User;
use Illuminate\Auth\Events\Verified;
use Illuminate\Console\Command;

class UserVerifyCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'admin:user:verify
                { email : The email of the user to verify }';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Verify the email address of an user';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $email = $this->argument('email');

        $this->info('Start verifying user with email "'.$email.'"');

        /** @var User|null $user */
        $user = User::query()->where('email', $email)
            ->where('is_placeholder', '=', false)
            ->first();

        if ($user === null) {
            $this->error('User with email "'.$email.'" not found.');

            return self::FAILURE;
        }

        if ($user->hasVerifiedEmail()) {
            $this->info('User with email "'.$email.'" already verified.');

            return self::FAILURE;
        }

        $user->markEmailAsVerified();
        event(new Verified($user));

        $this->info('User with email "'.$email.'" has been verified.');

        return self::SUCCESS;
    }
}


================================================
FILE: app/Console/Commands/Auth/AuthSendReminderForExpiringApiTokensCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands\Auth;

use App\Mail\AuthApiTokenExpirationReminderMail;
use App\Mail\AuthApiTokenExpiredMail;
use App\Models\Passport\Token;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Mail;

class AuthSendReminderForExpiringApiTokensCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'auth:send-mails-expiring-api-tokens '.
        ' { --dry-run : Do not actually send emails or save anything to the database, just output what would happen }';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Sends emails about expiring API tokens, one week before and when they expired.';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $dryRun = (bool) $this->option('dry-run');
        if ($dryRun) {
            $this->comment('Running in dry-run mode. No emails will be sent and nothing will be saved to the database.');
        }

        $this->comment('Sending reminder emails about expiring API tokens...');
        $sentMails = 0;
        Token::query()
            ->where('expires_at', '<=', Carbon::now()->addDays(7))
            ->whereNull('reminder_sent_at')
            ->with([
                'client',
                'user',
            ])
            ->whereHas('user', function (Builder $query): void {
                /** @var Builder<User> $query */
                $query->where('is_placeholder', '=', false);
            })
            ->isApiToken(true)
            ->orderBy('created_at', 'asc')
            ->chunk(500, function (Collection $tokens) use ($dryRun, &$sentMails): void {
                /** @var Collection<int, Token> $tokens */
                foreach ($tokens as $token) {
                    $user = $token->user;
                    $this->info('Start sending email to user "'.$user->email.'" ('.$user->getKey().') reminding about API token '.$token->getKey());
                    $sentMails++;
                    if (! $dryRun) {
                        Mail::to($user->email)
                            ->queue(new AuthApiTokenExpirationReminderMail($token, $user));
                        $token->reminder_sent_at = Carbon::now();
                        $token->save();
                    }
                }
            });
        $this->comment('Finished sending '.$sentMails.' expiring API token emails...');

        $this->comment('Sent emails about expired API tokens');
        $sentMails = 0;
        Token::query()
            ->where('expires_at', '<=', Carbon::now())
            ->whereNull('expired_info_sent_at')
            ->with([
                'client',
                'user',
            ])
            ->whereHas('user', function (Builder $query): void {
                /** @var Builder<User> $query */
                $query->where('is_placeholder', '=', false);
            })
            ->isApiToken(true)
            ->orderBy('created_at', 'asc')
            ->chunk(500, function (Collection $tokens) use ($dryRun, &$sentMails): void {
                /** @var Collection<int, Token> $tokens */
                foreach ($tokens as $token) {
                    $user = $token->user;
                    $this->info('Start sending email to user "'.$user->email.'" ('.$user->getKey().') about expired API token '.$token->getKey());
                    $sentMails++;
                    if (! $dryRun) {
                        Mail::to($user->email)
                            ->queue(new AuthApiTokenExpiredMail($token, $user));
                        $token->expired_info_sent_at = Carbon::now();
                        $token->save();
                    }
                }
            });
        $this->comment('Finished sending '.$sentMails.' expired API token emails...');

        return self::SUCCESS;
    }
}


================================================
FILE: app/Console/Commands/Correction/CorrectionPlaceholderMembersCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands\Correction;

use App\Enums\Role;
use App\Models\Member;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Builder;

class CorrectionPlaceholderMembersCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'correction:placeholder-members '.
        ' { --dry-run : Do not actually save anything to the database, just output what would happen }';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Sets all members who belong to a placeholder user to role placeholder';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $this->comment('Sets all members who belong to a placeholder user to role placeholder...');
        $dryRun = (bool) $this->option('dry-run');
        if ($dryRun) {
            $this->comment('Running in dry-run mode. Nothing will be saved to the database.');
        }

        $members = Member::query()
            ->where('role', '!=', Role::Placeholder->value)
            ->whereHas('user', function (Builder $builder): void {
                /** @var Builder<User> $builder */
                $builder->where('is_placeholder', '=', true);
            })
            ->get();
        foreach ($members as $member) {
            /** @var Member $member */
            $member->role = Role::Placeholder->value;
            if (! $dryRun) {
                $member->save();
            }
            $this->line('Set role of member (id='.$member->getKey().') to placeholder');
        }

        return self::SUCCESS;
    }
}


================================================
FILE: app/Console/Commands/Report/ReportSetExpiredToPrivateCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands\Report;

use App\Models\Report;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Carbon;
use LogicException;

class ReportSetExpiredToPrivateCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'report:set-expired-to-private '.
        ' { --dry-run : Do not actually save anything to the database, just output what would happen }';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Makes public reports private if the public_until date has passed.';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $this->comment('Makes public reports private if the public_until date has passed...');
        $dryRun = (bool) $this->option('dry-run');
        if ($dryRun) {
            $this->comment('Running in dry-run mode. Nothing will be saved to the database.');
        }

        $resetReports = 0;
        Report::query()
            ->where('public_until', '<', Carbon::now())
            ->orderBy('created_at', 'asc')
            ->chunk(500, function (Collection $reports) use ($dryRun, &$resetReports): void {
                /** @var Collection<int, Report> $reports */
                foreach ($reports as $report) {
                    $publicUntil = $report->public_until;
                    if ($publicUntil === null) {
                        throw new LogicException('public_until should not be null');
                    }
                    $this->info('Make report "'.$report->name.'" ('.$report->getKey().') private, expired: '.
                        $publicUntil->toIso8601ZuluString().' ('.$publicUntil->diffForHumans().')');
                    $resetReports++;
                    if (! $dryRun) {
                        $report->is_public = false;
                        $report->share_secret = null;
                        $report->save();
                    }
                }
            });

        $this->comment('Finished setting '.$resetReports.' expired reports to private...');

        return self::SUCCESS;
    }
}


================================================
FILE: app/Console/Commands/SelfHost/SelfHostCheckForUpdateCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands\SelfHost;

use App\Service\ApiService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;

class SelfHostCheckForUpdateCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'self-host:check-for-update';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $apiService = app(ApiService::class);

        $latestVersion = $apiService->checkForUpdate();
        if ($latestVersion === null) {
            $this->error('Failed to check for update, check the logs for more information.');

            return self::FAILURE;
        }

        // Note: Cache for 13 hours, because the command runs twice daily (every 12 hours).
        Cache::put('latest_version', $latestVersion, 60 * 60 * 12);

        return self::SUCCESS;
    }
}


================================================
FILE: app/Console/Commands/SelfHost/SelfHostDatabaseConsistency.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands\SelfHost;

use Illuminate\Console\Command;
use Illuminate\Database\Query\Builder;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class SelfHostDatabaseConsistency extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'self-host:database-consistency';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $hadAProblem = false;

        // Task need to be part of project in time entries
        $problems = DB::table('time_entries')
            ->select(['time_entries.id as id'])
            ->join('tasks', 'time_entries.task_id', '=', 'tasks.id')
            ->where('tasks.project_id', '!=', DB::raw('time_entries.project_id'))
            ->get();
        $this->logProblems($problems, 'Time entries have a task that does not belong to the project of the time entry', $hadAProblem);

        // Client id is the client id of the project
        $problems = DB::table('time_entries')
            ->select(['time_entries.id as id'])
            ->join('projects', 'time_entries.project_id', '=', 'projects.id')
            ->where(DB::raw('coalesce(projects.client_id::varchar, \'\')'), '!=', DB::raw('coalesce(time_entries.client_id::varchar, \'\')'))
            ->get();
        $this->logProblems($problems, 'Time entries have a client that does not match the client of the project', $hadAProblem);

        // Client id can only be not null if the project id is not null
        $problems = DB::table('time_entries')
            ->select(['time_entries.id as id'])
            ->whereNotNull('client_id')
            ->whereNull('project_id')
            ->get();
        $this->logProblems($problems, 'Time entries have a client but no project', $hadAProblem);

        // Every user needs to be a member of at least one organization
        $problems = DB::table('users')
            ->select(['users.id as id'])
            ->leftJoin('members', 'users.id', '=', 'members.user_id')
            ->whereNull('members.id')
            ->get();
        $this->logProblems($problems, 'Users are not member of any organization', $hadAProblem);

        // Every organization needs at least an owner
        $problems = DB::table('organizations')
            ->select(['organizations.id as id'])
            ->leftJoin('members', function (JoinClause $join): void {
                $join->on('organizations.id', '=', 'members.organization_id')
                    ->where('members.role', '=', 'owner');
            })
            ->whereNull('members.id')
            ->get();
        $this->logProblems($problems, 'Organizations without an owner', $hadAProblem);

        // Every member can only have one running time entry
        $problems = DB::table('time_entries')
            ->select(['user_id as id'])
            ->whereNull('end')
            ->groupBy('user_id')
            ->havingRaw('count(*) > 1')
            ->get(['user_id', DB::raw('count(*) as count')]);
        $this->logProblems($problems, 'Users with more than one running time entry', $hadAProblem);

        // Users have a current organization that they are not a member of
        $problems = DB::table('users')
            ->select(['users.id as id'])
            ->whereNotNull('current_team_id')
            ->whereNotIn('current_team_id', function (Builder $query): void {
                $query->select('organization_id')
                    ->from('members')
                    ->whereColumn('members.user_id', 'users.id');
            })->get();
        $this->logProblems($problems, 'Users have a current organization that they are not a member of', $hadAProblem);

        return $hadAProblem ? self::FAILURE : self::SUCCESS;
    }

    /**
     * @param  Collection<int, \stdClass>  $problems
     */
    private function logProblems(Collection $problems, string $message, bool &$hadAProblem): void
    {
        $message = 'Consistency problem: '.$message;
        if ($problems->isNotEmpty()) {
            $ids = $problems->pluck('id');
            $hadAProblem = true;
            Log::error($message, [
                'ids' => $ids,
            ]);

            $error = $message;
            foreach ($ids as $id) {
                $error .= "\n  - ".$id;
            }
            $this->error($error);
        }
    }
}


================================================
FILE: app/Console/Commands/SelfHost/SelfHostGenerateKeysCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands\SelfHost;

use Illuminate\Console\Command;
use Illuminate\Encryption\Encrypter;
use Illuminate\Support\Str;
use phpseclib3\Crypt\RSA;

class SelfHostGenerateKeysCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'self-host:generate-keys
                { --length=4096 : The length of the passport private key }
                { --multi-line : Whether to output the keys in multiple lines }
                { --format=env : The format of the output (env, yaml) }';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Generate random keys for the env variables.';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $format = $this->option('format');
        $key = RSA::createKey((int) $this->option('length'));
        $multiLine = (bool) $this->option('multi-line');

        $publicKey = (string) $key->getPublicKey();
        $privateKey = (string) $key;
        $appKey = 'base64:'.base64_encode(Encrypter::generateKey(config('app.cipher')));

        if ($format === 'env') {
            $this->line('APP_KEY="'.$appKey.'"');
            if ($multiLine) {
                $this->line('PASSPORT_PRIVATE_KEY="'.Str::replace("\r\n", "\n", $privateKey).'"');
                $this->line('PASSPORT_PUBLIC_KEY="'.Str::replace("\r\n", "\n", $publicKey).'"');
            } else {
                $this->line('PASSPORT_PRIVATE_KEY="'.Str::replace("\r\n", '\n', $privateKey).'"');
                $this->line('PASSPORT_PUBLIC_KEY="'.Str::replace("\r\n", '\n', $publicKey).'"');
            }
        } elseif ($format === 'yaml') {
            $this->line('APP_KEY: "'.$appKey.'"');
            $this->line("PASSPORT_PRIVATE_KEY: |\n  ".Str::replace("\r\n", "\n  ", $privateKey));
            $this->line("PASSPORT_PUBLIC_KEY: |\n  ".Str::replace("\r\n", "\n  ", $publicKey));
        } else {
            $this->error('Invalid format');

            return self::FAILURE;
        }

        return self::SUCCESS;
    }
}


================================================
FILE: app/Console/Commands/SelfHost/SelfHostTelemetryCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands\SelfHost;

use App\Service\ApiService;
use Illuminate\Console\Command;

class SelfHostTelemetryCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'self-host:telemetry';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $apiService = app(ApiService::class);

        $success = $apiService->telemetry();

        if (! $success) {
            $this->error('Failed to send telemetry data, check the logs for more information.');

            return self::FAILURE;

        }

        return self::SUCCESS;
    }
}


================================================
FILE: app/Console/Commands/Test/TestEmailCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands\Test;

use Illuminate\Console\Command;
use Illuminate\Mail\Message;
use Illuminate\Support\Facades\Mail;

class TestEmailCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'test:email { email : Email address to send the email to }';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'This test command sends an email.';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $email = $this->argument('email');
        Mail::raw('Hello World!', function (Message $message) use ($email): void {
            $message->to($email)
                ->subject('Test Email')
                ->html('<h1>Hello World!</h1>');
        });

        return self::SUCCESS;
    }
}


================================================
FILE: app/Console/Commands/Test/TestJobCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands\Test;

use App\Jobs\Test\TestJob;
use App\Models\User;
use Illuminate\Console\Command;

class TestJobCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'test:job {--fail}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'This test command start an async job.';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $user = User::firstOrFail();
        $fail = (bool) $this->option('fail');

        TestJob::dispatch($user, 'Test job message.', $fail);

        return self::SUCCESS;
    }
}


================================================
FILE: app/Console/Commands/Test/TestOutputCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands\Test;

use Illuminate\Console\Command;

class TestOutputCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'test:output';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'This test command outputs some text.';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $this->info('Test command output');
        $this->error('Test command output error');

        return self::SUCCESS;
    }
}


================================================
FILE: app/Console/Commands/TimeEntry/TimeEntrySendStillRunningMailsCommand.php
================================================
<?php

declare(strict_types=1);

namespace App\Console\Commands\TimeEntry;

use App\Mail\TimeEntryStillRunningMail;
use App\Models\TimeEntry;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Mail;

class TimeEntrySendStillRunningMailsCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'time-entry:send-still-running-mails '.
        ' { --dry-run : Do not actually send emails or save anything to the database, just output what would happen }';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Sends emails to users who have running time entries for more than 8 hours.';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $this->comment('Sending still running time entry emails...');
        $dryRun = (bool) $this->option('dry-run');
        if ($dryRun) {
            $this->comment('Running in dry-run mode. No emails will be sent and nothing will be saved to the database.');
        }

        $sentMails = 0;
        TimeEntry::query()
            ->whereNull('end')
            ->where('start', '<', now()->subHours(8))
            ->whereNull('still_active_email_sent_at')
            ->with([
                'user',
            ])
            ->whereHas('user', function (Builder $query): void {
                /** @var Builder<User> $query */
                $query->where('is_placeholder', '=', false);
            })
            ->orderBy('created_at', 'asc')
            ->chunk(500, function (Collection $timeEntries) use ($dryRun, &$sentMails): void {
                /** @var Collection<int, TimeEntry> $timeEntries */
                foreach ($timeEntries as $timeEntry) {
                    $user = $timeEntry->user;
                    $this->info('Start sending email to user "'.$user->email.'" ('.$user->getKey().') for time entry '.$timeEntry->getKey());
                    $sentMails++;
                    if (! $dryRun) {
                        Mail::to($user->email)
                            ->queue(new TimeEntryStillRunningMail($timeEntry, $user));
                        $timeEntry->still_active_email_sent_at = Carbon::now();
                        $timeEntry->save();
                    }
                }
            });

        $this->comment('Finished sending '.$sentMails.' still running time entry emails...');

        return self::SUCCESS;
    }
}


================================================
FILE: app/Console/Kernel.php
================================================
<?php

declare(strict_types=1);

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    /**
     * Define the application's command schedule.
     */
    protected function schedule(Schedule $schedule): void
    {
        $schedule->command('time-entry:send-still-running-mails')
            ->when(fn (): bool => config('scheduling.tasks.time_entry_send_still_running_mails'))
            ->everyTenMinutes();

        $schedule->command('auth:send-mails-expiring-api-tokens')
            ->when(fn (): bool => config('scheduling.tasks.auth_send_mails_expiring_api_tokens'))
            ->everyTenMinutes();

        if (config('app.key') && (config('scheduling.tasks.self_hosting_check_for_update') || config('scheduling.tasks.self_hosting_telemetry'))) {
            // Convert string to a stable integer for seeding
            /** @var int $seed Take the first 8 hex chars → 32-bit int */
            $seed = hexdec(substr(hash('md5', config('app.key')), 0, 8));
            $seed = abs($seed); // Ensure it's positive
            mt_srand($seed);
            $firstHour = mt_rand(0, 23);
            $secondHour = ($firstHour + 12) % 24;
            $minuteOffset = mt_rand(0, 59);
            mt_srand(null); // Reset the random number generator

            if (config('scheduling.tasks.self_hosting_check_for_update')) {
                $schedule->command('self-host:check-for-update')
                    ->twiceDailyAt($firstHour, $secondHour, $minuteOffset);
            }

            if (config('scheduling.tasks.self_hosting_telemetry')) {
                $schedule->command('self-host:telemetry')
                    ->twiceDailyAt($firstHour, $secondHour, $minuteOffset);
            }
        }

        $schedule->command('self-host:database-consistency')
            ->when(fn (): bool => config('scheduling.tasks.self_hosting_database_consistency'))
            ->everySixHours();
    }

    /**
     * Register the commands for the application.
     */
    protected function commands(): void
    {
        $this->load(__DIR__.'/Commands');
    }
}


================================================
FILE: app/Enums/CurrencyFormat.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums;

use Datomatic\LaravelEnumHelper\LaravelEnumHelper;

enum CurrencyFormat: string
{
    use LaravelEnumHelper;

    case ISOCodeBeforeWithSpace = 'iso-code-before-with-space';
    case ISOCodeAfterWithSpace = 'iso-code-after-with-space';

    case SymbolBefore = 'symbol-before';

    case SymbolAfter = 'symbol-after';

    case SymbolBeforeWithSpace = 'symbol-before-with-space';

    case SymbolAfterWithSpace = 'symbol-after-with-space';

    /**
     * @return array<string, string>
     */
    public static function toSelectArray(): array
    {
        $selectArray = [];
        foreach (self::values() as $value) {
            $selectArray[(string) $value] = (string) __('enum.currency_format.'.$value);
        }

        return $selectArray;
    }
}


================================================
FILE: app/Enums/DateFormat.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums;

use Datomatic\LaravelEnumHelper\LaravelEnumHelper;

enum DateFormat: string
{
    use LaravelEnumHelper;

    case PointSeparatedDMYYYY = 'point-separated-d-m-yyyy';
    case SlashSeparatedMMDDYYYY = 'slash-separated-mm-dd-yyyy';

    case SlashSeparatedDDMMYYYY = 'slash-separated-dd-mm-yyyy';

    case HyphenSeparatedDDMMYYY = 'hyphen-separated-dd-mm-yyyy';

    case HyphenSeparatedMMDDDYYYY = 'hyphen-separated-mm-dd-yyyy';

    case HyphenSeparatedYYYYMMDD = 'hyphen-separated-yyyy-mm-dd';

    public function toCarbonFormat(): string
    {
        return match ($this->value) {
            self::PointSeparatedDMYYYY->value => 'j.n.Y',
            self::SlashSeparatedMMDDYYYY->value => 'm/d/Y',
            self::SlashSeparatedDDMMYYYY->value => 'd/m/Y',
            self::HyphenSeparatedDDMMYYY->value => 'd-m-Y',
            self::HyphenSeparatedMMDDDYYYY->value => 'm-d-Y',
            self::HyphenSeparatedYYYYMMDD->value => 'Y-m-d',
        };
    }

    /**
     * @return array<string, string>
     */
    public static function toSelectArray(): array
    {
        $selectArray = [];
        foreach (self::values() as $value) {
            $selectArray[(string) $value] = (string) __('enum.date_format.'.$value);
        }

        return $selectArray;
    }
}


================================================
FILE: app/Enums/ExportFormat.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums;

use Maatwebsite\Excel\Excel;

enum ExportFormat: string
{
    case CSV = 'csv';
    case PDF = 'pdf';
    case XLSX = 'xlsx';
    case ODS = 'ods';

    public function getFileExtension(): string
    {
        return match ($this) {
            self::CSV => 'csv',
            self::PDF => 'pdf',
            self::XLSX => 'xlsx',
            self::ODS => 'ods',
        };
    }

    public function getExportPackageType(): string
    {
        return match ($this) {
            self::CSV => Excel::CSV,
            self::PDF => Excel::MPDF,
            self::XLSX => Excel::XLSX,
            self::ODS => Excel::ODS,
        };
    }
}


================================================
FILE: app/Enums/IntervalFormat.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums;

use Datomatic\LaravelEnumHelper\LaravelEnumHelper;

enum IntervalFormat: string
{
    use LaravelEnumHelper;

    case Decimal = 'decimal';
    case HoursMinutes = 'hours-minutes';

    case HoursMinutesColonSeparated = 'hours-minutes-colon-separated';

    case HoursMinutesSecondsColonSeparated = 'hours-minutes-seconds-colon-separated';

    /**
     * @return array<string, string>
     */
    public static function toSelectArray(): array
    {
        $selectArray = [];
        foreach (self::values() as $value) {
            $selectArray[(string) $value] = (string) __('enum.interval_format.'.$value);
        }

        return $selectArray;
    }
}


================================================
FILE: app/Enums/NumberFormat.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums;

use Datomatic\LaravelEnumHelper\LaravelEnumHelper;

/**
 * @info https://en.wikipedia.org/wiki/Decimal_separator
 */
enum NumberFormat: string
{
    use LaravelEnumHelper;

    case ThousandsPointDecimalComma = 'point-comma';

    case ThousandsCommaDecimalPoint = 'comma-point';
    case ThousandsSpaceDecimalComma = 'space-comma';

    case ThousandsSpaceDecimalPoint = 'space-point';

    case ThousandsApostropheDecimalPoint = 'apostrophe-point';

    /**
     * @return array<string, string>
     */
    public static function toSelectArray(): array
    {
        $selectArray = [];
        foreach (self::values() as $value) {
            $selectArray[(string) $value] = (string) __('enum.number_format.'.$value);
        }

        return $selectArray;
    }
}


================================================
FILE: app/Enums/Role.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums;

enum Role: string
{
    case Owner = 'owner';
    case Admin = 'admin';
    case Manager = 'manager';
    case Employee = 'employee';
    case Placeholder = 'placeholder';
}


================================================
FILE: app/Enums/TimeEntryAggregationType.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums;

use Datomatic\LaravelEnumHelper\LaravelEnumHelper;

enum TimeEntryAggregationType: string
{
    use LaravelEnumHelper;

    case Day = 'day';
    case Week = 'week';
    case Month = 'month';
    case Year = 'year';
    case User = 'user';
    case Project = 'project';
    case Task = 'task';
    case Client = 'client';
    case Billable = 'billable';
    case Description = 'description';
    case Tag = 'tag';

    public static function fromInterval(TimeEntryAggregationTypeInterval $timeEntryAggregationTypeInterval): TimeEntryAggregationType
    {
        return match ($timeEntryAggregationTypeInterval) {
            TimeEntryAggregationTypeInterval::Day => TimeEntryAggregationType::Day,
            TimeEntryAggregationTypeInterval::Week => TimeEntryAggregationType::Week,
            TimeEntryAggregationTypeInterval::Month => TimeEntryAggregationType::Month,
            TimeEntryAggregationTypeInterval::Year => TimeEntryAggregationType::Year,
        };
    }

    public function toInterval(): ?TimeEntryAggregationTypeInterval
    {
        return match ($this) {
            TimeEntryAggregationType::Day => TimeEntryAggregationTypeInterval::Day,
            TimeEntryAggregationType::Week => TimeEntryAggregationTypeInterval::Week,
            TimeEntryAggregationType::Month => TimeEntryAggregationTypeInterval::Month,
            TimeEntryAggregationType::Year => TimeEntryAggregationTypeInterval::Year,
            default => null
        };
    }
}


================================================
FILE: app/Enums/TimeEntryAggregationTypeInterval.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums;

enum TimeEntryAggregationTypeInterval: string
{
    case Day = 'day';
    case Week = 'week';
    case Month = 'month';
    case Year = 'year';
}


================================================
FILE: app/Enums/TimeEntryRoundingType.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums;

use Datomatic\LaravelEnumHelper\LaravelEnumHelper;

enum TimeEntryRoundingType: string
{
    use LaravelEnumHelper;

    case Up = 'up';
    case Down = 'down';
    case Nearest = 'nearest';
}


================================================
FILE: app/Enums/TimeFormat.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums;

use Datomatic\LaravelEnumHelper\LaravelEnumHelper;

enum TimeFormat: string
{
    use LaravelEnumHelper;

    case TwelveHours = '12-hours';
    case TwentyFourHours = '24-hours';

    /**
     * @return array<string, string>
     */
    public static function toSelectArray(): array
    {
        $selectArray = [];
        foreach (self::values() as $value) {
            $selectArray[(string) $value] = (string) __('enum.time_format.'.$value);
        }

        return $selectArray;
    }
}


================================================
FILE: app/Enums/Weekday.php
================================================
<?php

declare(strict_types=1);

namespace App\Enums;

use Datomatic\LaravelEnumHelper\LaravelEnumHelper;
use Illuminate\Support\Carbon;

enum Weekday: string
{
    use LaravelEnumHelper;

    case Monday = 'monday';
    case Tuesday = 'tuesday';
    case Wednesday = 'wednesday';
    case Thursday = 'thursday';
    case Friday = 'friday';
    case Saturday = 'saturday';
    case Sunday = 'sunday';

    public function toEndOfWeek(): self
    {
        return match ($this) {
            Weekday::Monday => Weekday::Sunday,
            Weekday::Tuesday => Weekday::Monday,
            Weekday::Wednesday => Weekday::Tuesday,
            Weekday::Thursday => Weekday::Wednesday,
            Weekday::Friday => Weekday::Thursday,
            Weekday::Saturday => Weekday::Friday,
            Weekday::Sunday => Weekday::Saturday,
        };
    }

    public function carbonWeekDay(): int
    {
        return match ($this) {
            Weekday::Monday => Carbon::MONDAY,
            Weekday::Tuesday => Carbon::TUESDAY,
            Weekday::Wednesday => Carbon::WEDNESDAY,
            Weekday::Thursday => Carbon::THURSDAY,
            Weekday::Friday => Carbon::FRIDAY,
            Weekday::Saturday => Carbon::SATURDAY,
            Weekday::Sunday => Carbon::SUNDAY,
        };
    }

    /**
     * @return array<string, string>
     */
    public static function toSelectArray(): array
    {
        return [
            Weekday::Monday->value => __('enum.weekday.'.Weekday::Monday->value),
            Weekday::Tuesday->value => __('enum.weekday.'.Weekday::Tuesday->value),
            Weekday::Wednesday->value => __('enum.weekday.'.Weekday::Wednesday->value),
            Weekday::Thursday->value => __('enum.weekday.'.Weekday::Thursday->value),
            Weekday::Friday->value => __('enum.weekday.'.Weekday::Friday->value),
            Weekday::Saturday->value => __('enum.weekday.'.Weekday::Saturday->value),
            Weekday::Sunday->value => __('enum.weekday.'.Weekday::Sunday->value),
        ];
    }
}


================================================
FILE: app/Events/AfterCreateOrganization.php
================================================
<?php

declare(strict_types=1);

namespace App\Events;

use App\Models\Organization;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

/**
 * This event is fired after an organization has been created.
 * This event does NOT fire when an organization is created as part of a registration.
 */
class AfterCreateOrganization
{
    use Dispatchable;
    use SerializesModels;

    public Organization $organization;

    public function __construct(Organization $organization)
    {
        $this->organization = $organization;
    }
}


================================================
FILE: app/Events/BeforeOrganizationDeletion.php
================================================
<?php

declare(strict_types=1);

namespace App\Events;

use App\Models\Organization;
use Illuminate\Foundation\Events\Dispatchable;

class BeforeOrganizationDeletion
{
    use Dispatchable;

    public Organization $organization;

    public function __construct(Organization $organization)
    {
        $this->organization = $organization;
    }
}


================================================
FILE: app/Events/DatabaseSeederAfterSeed.php
================================================
<?php

declare(strict_types=1);

namespace App\Events;

use Illuminate\Foundation\Events\Dispatchable;

class DatabaseSeederAfterSeed
{
    use Dispatchable;

    public function __construct() {}
}


================================================
FILE: app/Events/DatabaseSeederBeforeDelete.php
================================================
<?php

declare(strict_types=1);

namespace App\Events;

use Illuminate\Foundation\Events\Dispatchable;

class DatabaseSeederBeforeDelete
{
    use Dispatchable;

    public function __construct() {}
}


================================================
FILE: app/Events/MemberMadeToPlaceholder.php
================================================
<?php

declare(strict_types=1);

namespace App\Events;

use App\Models\Member;
use App\Models\Organization;
use Illuminate\Foundation\Events\Dispatchable;

class MemberMadeToPlaceholder
{
    use Dispatchable;

    public Organization $organization;

    public Member $member;

    public function __construct(Member $member, Organization $organization)
    {
        $this->member = $member;
        $this->organization = $organization;
    }
}


================================================
FILE: app/Events/MemberRemoved.php
================================================
<?php

declare(strict_types=1);

namespace App\Events;

use App\Models\Member;
use App\Models\Organization;
use Illuminate\Foundation\Events\Dispatchable;

class MemberRemoved
{
    use Dispatchable;

    public Organization $organization;

    public Member $member;

    public function __construct(Member $member, Organization $organization)
    {
        $this->member = $member;
        $this->organization = $organization;
    }
}


================================================
FILE: app/Events/NewsletterRegistered.php
================================================
<?php

declare(strict_types=1);

namespace App\Events;

use Illuminate\Foundation\Events\Dispatchable;

class NewsletterRegistered
{
    use Dispatchable;

    public string $name;

    public string $email;

    public string $id;

    /**
     * Create a new event instance.
     */
    public function __construct(string $name, string $email, string $id)
    {
        $this->name = $name;
        $this->email = $email;
        $this->id = $id;
    }
}


================================================
FILE: app/Exceptions/Api/ApiException.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use LogicException;

abstract class ApiException extends Exception
{
    public const string KEY = 'api_exception';

    public function __construct()
    {
        parent::__construct(static::KEY);
    }

    /**
     * Render the exception into an HTTP response.
     */
    public function render(Request $request): JsonResponse
    {
        return response()
            ->json([
                'error' => true,
                'key' => $this->getKey(),
                'message' => $this->getTranslatedMessage(),
            ], 400);
    }

    /**
     * Get the key for the exception.
     */
    public function getKey(): string
    {
        $key = static::KEY;

        if ($key === ApiException::KEY) {
            throw new LogicException('API exceptions need the KEY constant defined.');
        }

        return $key;
    }

    /**
     * Get the translated message for the exception.
     */
    public function getTranslatedMessage(): string
    {
        return __('exceptions.api.'.$this->getKey());
    }

    /**
     * Report the exception.
     *
     * @return bool true means the exception handler will not report it again
     */
    public function report(): bool
    {
        // TODO: temporary activated
        return false;
    }
}


================================================
FILE: app/Exceptions/Api/CanNotDeleteUserWhoIsOwnerOfOrganizationWithMultipleMembers.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class CanNotDeleteUserWhoIsOwnerOfOrganizationWithMultipleMembers extends ApiException
{
    public const string KEY = 'can_not_delete_user_who_is_owner_of_organization_with_multiple_members';
}


================================================
FILE: app/Exceptions/Api/CanNotRemoveOwnerFromOrganization.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class CanNotRemoveOwnerFromOrganization extends ApiException
{
    public const string KEY = 'can_not_remove_owner_from_organization';
}


================================================
FILE: app/Exceptions/Api/ChangingRoleOfPlaceholderIsNotAllowed.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class ChangingRoleOfPlaceholderIsNotAllowed extends ApiException
{
    public const string KEY = 'changing_role_of_placeholder_is_not_allowed';
}


================================================
FILE: app/Exceptions/Api/ChangingRoleToPlaceholderIsNotAllowed.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class ChangingRoleToPlaceholderIsNotAllowed extends ApiException
{
    public const string KEY = 'changing_role_to_placeholder_is_not_allowed';
}


================================================
FILE: app/Exceptions/Api/EntityStillInUseApiException.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class EntityStillInUseApiException extends ApiException
{
    private string $modelToDelete;

    private string $modelInUse;

    public function __construct(string $modelToDelete, string $modelInUse)
    {
        parent::__construct();
        $this->modelToDelete = $modelToDelete;
        $this->modelInUse = $modelInUse;
    }

    public const string KEY = 'entity_still_in_use';

    /**
     * Get the translated message for the exception.
     */
    #[\Override]
    public function getTranslatedMessage(): string
    {
        return __('exceptions.api.'.$this->getKey(), [
            'modelToDelete' => __('validation.entities.'.$this->modelToDelete),
            'modelInUse' => __('validation.entities.'.$this->modelInUse),
        ]);
    }
}


================================================
FILE: app/Exceptions/Api/FeatureIsNotAvailableInFreePlanApiException.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class FeatureIsNotAvailableInFreePlanApiException extends ApiException
{
    public const string KEY = 'feature_is_not_available_in_free_plan';
}


================================================
FILE: app/Exceptions/Api/InactiveUserCanNotBeUsedApiException.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class InactiveUserCanNotBeUsedApiException extends ApiException
{
    public const string KEY = 'inactive_user_can_not_be_used';
}


================================================
FILE: app/Exceptions/Api/InvitationForTheEmailAlreadyExistsApiException.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class InvitationForTheEmailAlreadyExistsApiException extends ApiException
{
    public const string KEY = 'invitation_for_the_email_already_exists';
}


================================================
FILE: app/Exceptions/Api/OnlyOwnerCanChangeOwnership.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class OnlyOwnerCanChangeOwnership extends ApiException
{
    public const string KEY = 'only_owner_can_change_ownership';
}


================================================
FILE: app/Exceptions/Api/OnlyPlaceholdersCanBeMergedIntoAnotherMember.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class OnlyPlaceholdersCanBeMergedIntoAnotherMember extends ApiException
{
    public const string KEY = 'only_placeholders_can_be_merged_into_another_member';
}


================================================
FILE: app/Exceptions/Api/OrganizationHasNoSubscriptionButMultipleMembersException.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class OrganizationHasNoSubscriptionButMultipleMembersException extends ApiException
{
    public const string KEY = 'organization_has_no_subscription_but_multiple_members';
}


================================================
FILE: app/Exceptions/Api/OrganizationNeedsAtLeastOneOwner.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class OrganizationNeedsAtLeastOneOwner extends ApiException
{
    public const string KEY = 'organization_needs_at_least_one_owner';
}


================================================
FILE: app/Exceptions/Api/OverlappingTimeEntryApiException.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class OverlappingTimeEntryApiException extends ApiException
{
    public const string KEY = 'overlapping_time_entry';
}


================================================
FILE: app/Exceptions/Api/PdfRendererIsNotConfiguredException.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class PdfRendererIsNotConfiguredException extends ApiException
{
    public const string KEY = 'pdf_renderer_is_not_configured';
}


================================================
FILE: app/Exceptions/Api/PersonalAccessClientIsNotConfiguredException.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class PersonalAccessClientIsNotConfiguredException extends ApiException
{
    public const string KEY = 'personal_access_client_is_not_configured';
}


================================================
FILE: app/Exceptions/Api/ThisPlaceholderCanNotBeInvitedUseTheMergeToolInsteadException.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class ThisPlaceholderCanNotBeInvitedUseTheMergeToolInsteadException extends ApiException
{
    public const string KEY = 'this_placeholder_can_not_be_invited_use_the_merge_tool_instead_api_exception';
}


================================================
FILE: app/Exceptions/Api/TimeEntryCanNotBeRestartedApiException.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class TimeEntryCanNotBeRestartedApiException extends ApiException
{
    public const string KEY = 'time_entry_can_not_be_restarted';
}


================================================
FILE: app/Exceptions/Api/TimeEntryStillRunningApiException.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class TimeEntryStillRunningApiException extends ApiException
{
    public const string KEY = 'time_entry_still_running';
}


================================================
FILE: app/Exceptions/Api/UserIsAlreadyMemberOfOrganizationApiException.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class UserIsAlreadyMemberOfOrganizationApiException extends ApiException
{
    public const string KEY = 'user_is_already_member_of_organization';
}


================================================
FILE: app/Exceptions/Api/UserIsAlreadyMemberOfProjectApiException.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class UserIsAlreadyMemberOfProjectApiException extends ApiException
{
    public const string KEY = 'user_is_already_member_of_project';
}


================================================
FILE: app/Exceptions/Api/UserNotPlaceholderApiException.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions\Api;

class UserNotPlaceholderApiException extends ApiException
{
    public const string KEY = 'user_not_placeholder';
}


================================================
FILE: app/Exceptions/Handler.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions;

use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Http\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Throwable;

class Handler extends ExceptionHandler
{
    /**
     * The list of the inputs that are never flashed to the session on validation exceptions.
     *
     * @var array<int, string>
     */
    protected $dontFlash = [
        'current_password',
        'password',
        'password_confirmation',
    ];

    /**
     * Register the exception handling callbacks for the application.
     */
    public function register(): void
    {
        $this->reportable(function (Throwable $e): void {
            //
        });
    }

    public function render($request, Throwable $e): Response|RedirectResponse
    {
        $response = parent::render($request, $e);

        if ($response->getStatusCode() === 419) {
            return back()->with([
                'message' => 'The page expired, please try again.',
            ]);
        }

        return $response;
    }
}


================================================
FILE: app/Exceptions/MovedToApiException.php
================================================
<?php

declare(strict_types=1);

namespace App\Exceptions;

use Symfony\Component\HttpKernel\Exception\HttpException;

class MovedToApiException extends HttpException
{
    public function __construct()
    {
        parent::__construct(403, 'Moved to API');
    }
}


================================================
FILE: app/Extensions/Auditing/Resolvers/CustomIpAddressResolver.php
================================================
<?php

declare(strict_types=1);

namespace App\Extensions\Auditing\Resolvers;

use Illuminate\Support\Facades\Request;
use OwenIt\Auditing\Contracts\Auditable;
use OwenIt\Auditing\Contracts\Resolver;

class CustomIpAddressResolver implements Resolver
{
    private static function anonymizeIpAddress(string $ipAddress): string
    {
        /** @source https://stackoverflow.com/a/48777412 */
        return preg_replace(
            ['/\.\d*$/', '/[\da-f]*:[\da-f]*$/'],
            ['.0', '0:0'],
            $ipAddress
        );
    }

    public static function resolve(Auditable $auditable): string
    {
        $ip = $auditable->preloadedResolverData['ip_address'] ?? Request::ip();

        if ($ip !== null) {
            $ip = self::anonymizeIpAddress($ip);
        }

        return $ip;
    }
}


================================================
FILE: app/Extensions/Fortify/CustomLoginResponse.php
================================================
<?php

declare(strict_types=1);

namespace App\Extensions\Fortify;

use Illuminate\Http\Request;
use Inertia\Inertia;
use Laravel\Fortify\Http\Responses\LoginResponse;
use Symfony\Component\HttpFoundation\Response;

class CustomLoginResponse extends LoginResponse
{
    /**
     * Create an HTTP response that represents the object.
     *
     * @param  Request  $request
     */
    public function toResponse($request): Response
    {
        $redirectPath = session()->pull('url.intended', route('dashboard', [], false));

        return $request->wantsJson()
            ? response()->json(['two_factor' => false])
            : Inertia::location($redirectPath);
    }
}


================================================
FILE: app/Extensions/Fortify/CustomTwoFactorLoginResponse.php
================================================
<?php

declare(strict_types=1);

namespace App\Extensions\Fortify;

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Laravel\Fortify\Contracts\TwoFactorLoginResponse as TwoFactorLoginResponseContract;
use Symfony\Component\HttpFoundation\Response;

class CustomTwoFactorLoginResponse implements TwoFactorLoginResponseContract
{
    /**
     * Create an HTTP response that represents the object.
     *
     * @param  Request  $request
     */
    public function toResponse($request): Response
    {
        $redirectPath = session()->pull('url.intended', route('dashboard', [], false));

        return $request->wantsJson()
            ? new JsonResponse('', 204)
            : Inertia::location($redirectPath);
    }
}


================================================
FILE: app/Extensions/Scramble/ApiExceptionTypeToSchema.php
================================================
<?php

declare(strict_types=1);

namespace App\Extensions\Scramble;

use App\Exceptions\Api\ApiException;
use Dedoc\Scramble\Extensions\ExceptionToResponseExtension;
use Dedoc\Scramble\Support\Generator\Reference;
use Dedoc\Scramble\Support\Generator\Response;
use Dedoc\Scramble\Support\Generator\Schema;
use Dedoc\Scramble\Support\Generator\Types as OpenApiTypes;
use Dedoc\Scramble\Support\Type\ObjectType;
use Dedoc\Scramble\Support\Type\Type;
use Illuminate\Support\Str;

class ApiExceptionTypeToSchema extends ExceptionToResponseExtension
{
    public function shouldHandle(Type $type): bool
    {
        return $type instanceof ObjectType
            && $type->isInstanceOf(ApiException::class);
    }

    public function toResponse(Type $type): Response
    {
        $validationResponseBodyType = (new OpenApiTypes\ObjectType)
            ->addProperty(
                'error',
                (new OpenApiTypes\BooleanType)
                    ->setDescription('Whether the response is an error.')
            )
            ->addProperty(
                'key',
                (new OpenApiTypes\StringType)
                    ->setDescription('Error key.')
            )
            ->addProperty(
                'message',
                (new OpenApiTypes\StringType)
                    ->setDescription('Error message.')
            )
            ->setRequired(['error', 'key', 'message']);

        return Response::make(400)
            ->description('API exception')
            ->setContent(
                'application/json',
                Schema::fromType($validationResponseBodyType)
            );
    }

    public function reference(ObjectType $type): Reference
    {
        return new Reference('responses', Str::start($type->name, '\\'), $this->components);
    }
}


================================================
FILE: app/Extensions/Scramble/PaginatedResourceCollectionTypeToSchema.php
================================================
<?php

declare(strict_types=1);

namespace App\Extensions\Scramble;

use App\Http\Resources\PaginatedResourceCollection;
use App\Http\Resources\V1\TimeEntry\TimeEntryCollection;
use Dedoc\Scramble\Extensions\TypeToSchemaExtension;
use Dedoc\Scramble\Support\Generator\Response;
use Dedoc\Scramble\Support\Generator\Schema;
use Dedoc\Scramble\Support\Generator\Types\ArrayType;
use Dedoc\Scramble\Support\Generator\Types\BooleanType;
use Dedoc\Scramble\Support\Generator\Types\IntegerType;
use Dedoc\Scramble\Support\Generator\Types\ObjectType as OpenApiObjectType;
use Dedoc\Scramble\Support\Generator\Types\StringType;
use Dedoc\Scramble\Support\Type\Generic;
use Dedoc\Scramble\Support\Type\ObjectType;
use Dedoc\Scramble\Support\Type\Type;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Resources\Json\JsonResource;

class PaginatedResourceCollectionTypeToSchema extends TypeToSchemaExtension
{
    public function shouldHandle(Type $type): bool
    {
        return $type instanceof ObjectType
            && $type->isInstanceOf(PaginatedResourceCollection::class);
    }

    public function toSchema(Type $type): ?OpenApiObjectType
    {
        /** @var Type|null $collectingClassType */
        $collectingClassType = $type->templateTypes[0] ?? null;

        if (! $collectingClassType instanceof ObjectType) {
            return null;
        }

        if (! $collectingClassType->isInstanceOf(JsonResource::class) && ! $collectingClassType->isInstanceOf(Model::class)) {
            return null;
        }

        $collectingType = $this->openApiTransformer->transform($collectingClassType);

        $newType = new OpenApiObjectType;
        $newType->addProperty('data', (new ArrayType)->setItems($collectingType));
        if ($type instanceof ObjectType && $type->isInstanceOf(TimeEntryCollection::class)) {
            $newType->addProperty(
                'meta',
                (new OpenApiObjectType)
                    ->addProperty('total', (new IntegerType)->setDescription('Total number of items being paginated.'))
                    ->setRequired(['total'])
            );
            $newType->setRequired(['data', 'meta']);
        } else {
            $newType->addProperty(
                'links',
                (new OpenApiObjectType)
                    ->addProperty('first', (new StringType)->nullable(true))
                    ->addProperty('last', (new StringType)->nullable(true))
                    ->addProperty('prev', (new StringType)->nullable(true))
                    ->addProperty('next', (new StringType)->nullable(true))
                    ->setRequired(['first', 'last', 'prev', 'next'])
            );
            $newType->addProperty(
                'meta',
                (new OpenApiObjectType)
                    ->addProperty('current_page', new IntegerType)
                    ->addProperty('from', (new IntegerType)->nullable(true))
                    ->addProperty('last_page', new IntegerType)
                    ->addProperty('links', (new ArrayType)->setItems(
                        (new OpenApiObjectType)
                            ->addProperty('url', (new StringType)->nullable(true))
                            ->addProperty('label', new StringType)
                            ->addProperty('active', new BooleanType)
                            ->setRequired(['url', 'label', 'active'])
                    )->setDescription('Generated paginator links.'))
                    ->addProperty('path', (new StringType)->nullable(true)->setDescription('Base path for paginator generated URLs.'))
                    ->addProperty('per_page', (new IntegerType)->setDescription('Number of items shown per page.'))
                    ->addProperty('to', (new IntegerType)->nullable(true)->setDescription('Number of the last item in the slice.'))
                    ->addProperty('total', (new IntegerType)->setDescription('Total number of items being paginated.'))
                    ->setRequired(['current_page', 'from', 'last_page', 'links', 'path', 'per_page', 'to', 'total'])
            );
            $newType->setRequired(['data', 'links', 'meta']);
        }

        return $newType;
    }

    /**
     * @param  Generic  $type
     */
    public function toResponse(Type $type): ?Response
    {
        /** @var ObjectType|null $collectingClassType */
        $collectingClassType = $type->templateTypes[0] ?? null;
        if (! $collectingClassType instanceof ObjectType) {
            return null;
        }
        $type = $this->toSchema($type);

        return Response::make(200)
            ->description('Paginated set of `'.$this->components->uniqueSchemaName($collectingClassType->name).'`')
            ->setContent('application/json', Schema::fromType($type));
    }
}


================================================
FILE: app/Filament/Resources/AuditResource/Pages/CreateAudit.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources\AuditResource\Pages;

use App\Filament\Resources\AuditResource;
use Filament\Resources\Pages\CreateRecord;

class CreateAudit extends CreateRecord
{
    protected static string $resource = AuditResource::class;
}


================================================
FILE: app/Filament/Resources/AuditResource/Pages/ListAudits.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources\AuditResource\Pages;

use App\Filament\Resources\AuditResource;
use Filament\Resources\Pages\ListRecords;

class ListAudits extends ListRecords
{
    protected static string $resource = AuditResource::class;

    protected function getHeaderActions(): array
    {
        return [];
    }
}


================================================
FILE: app/Filament/Resources/AuditResource/Pages/ViewAudit.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources\AuditResource\Pages;

use App\Filament\Resources\AuditResource;
use Filament\Resources\Pages\ViewRecord;

class ViewAudit extends ViewRecord
{
    protected static string $resource = AuditResource::class;
}


================================================
FILE: app/Filament/Resources/AuditResource.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources;

use App\Filament\Resources\AuditResource\Pages;
use App\Models\Audit;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Table;
use Illuminate\Support\Str;
use Novadaemon\FilamentPrettyJson\Form\PrettyJsonField;

class AuditResource extends Resource
{
    protected static ?string $model = Audit::class;

    protected static ?string $navigationIcon = 'heroicon-o-archive-box';

    protected static ?string $navigationGroup = 'System';

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                Forms\Components\TextInput::make('user_type')
                    ->maxLength(255),
                Forms\Components\TextInput::make('user_id'),
                Forms\Components\TextInput::make('event')
                    ->required()
                    ->maxLength(255),
                Forms\Components\TextInput::make('auditable_type')
                    ->required()
                    ->maxLength(255),
                Forms\Components\TextInput::make('auditable_id')
                    ->required(),
                PrettyJsonField::make('old_values'),
                PrettyJsonField::make('new_values'),
                Forms\Components\Textarea::make('url'),
                Forms\Components\TextInput::make('ip_address'),
                Forms\Components\TextInput::make('user_agent')
                    ->maxLength(1023),
                Forms\Components\TextInput::make('tags')
                    ->maxLength(255),
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\Columns\TextColumn::make('user.name'),
                Tables\Columns\TextColumn::make('event'),
                Tables\Columns\TextColumn::make('auditable_type'),
                Tables\Columns\TextColumn::make('auditable_id'),
                IconColumn::make('was_command')
                    ->getStateUsing(fn (Audit $record) => Str::startsWith($record->url, 'artisan '))
                    ->boolean(),
                Tables\Columns\TextColumn::make('created_at')
                    ->sortable()
                    ->dateTime(),
                Tables\Columns\TextColumn::make('updated_at')
                    ->sortable()
                    ->dateTime(),
            ])
            ->filters([
                //
            ])
            ->actions([
                Tables\Actions\ViewAction::make(),
            ])
            ->bulkActions([
            ])
            ->defaultSort('created_at', 'desc');
    }

    public static function getRelations(): array
    {
        return [
        ];
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\ListAudits::route('/'),
            'create' => Pages\CreateAudit::route('/create'),
            'view' => Pages\ViewAudit::route('/{record}'),
        ];
    }
}


================================================
FILE: app/Filament/Resources/ClientResource/Pages/CreateClient.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources\ClientResource\Pages;

use App\Filament\Resources\ClientResource;
use Filament\Resources\Pages\CreateRecord;

class CreateClient extends CreateRecord
{
    protected static string $resource = ClientResource::class;
}


================================================
FILE: app/Filament/Resources/ClientResource/Pages/EditClient.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources\ClientResource\Pages;

use App\Filament\Resources\ClientResource;
use Filament\Actions;
use Filament\Resources\Pages\EditRecord;

class EditClient extends EditRecord
{
    protected static string $resource = ClientResource::class;

    protected function getHeaderActions(): array
    {
        return [
            Actions\DeleteAction::make()
                ->icon('heroicon-m-trash'),
        ];
    }
}


================================================
FILE: app/Filament/Resources/ClientResource/Pages/ListClients.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources\ClientResource\Pages;

use App\Filament\Resources\ClientResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;

class ListClients extends ListRecords
{
    protected static string $resource = ClientResource::class;

    protected function getHeaderActions(): array
    {
        return [
            Actions\CreateAction::make()
                ->icon('heroicon-s-plus'),
        ];
    }
}


================================================
FILE: app/Filament/Resources/ClientResource.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources;

use App\Filament\Resources\ClientResource\Pages;
use App\Models\Client;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;

class ClientResource extends Resource
{
    protected static ?string $model = Client::class;

    protected static ?string $navigationIcon = 'heroicon-o-briefcase';

    protected static ?string $navigationGroup = 'Timetracking';

    protected static ?int $navigationSort = 4;

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                TextInput::make('name')
                    ->label('Name')
                    ->required(),
                Select::make('organization_id')
                    ->relationship(name: 'organization', titleAttribute: 'name')
                    ->label('Organization')
                    ->searchable(['name'])
                    ->required(),
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\Columns\TextColumn::make('name')
                    ->label('Name')
                    ->searchable()
                    ->sortable(),
                Tables\Columns\TextColumn::make('organization.name')
                    ->sortable()
                    ->label('Organization'),
                Tables\Columns\TextColumn::make('created_at')
                    ->label('Created at')
                    ->sortable(),
                Tables\Columns\TextColumn::make('updated_at')
                    ->label('Updated at')
                    ->sortable(),
            ])
            ->defaultSort('created_at', 'desc')
            ->filters([
                SelectFilter::make('organization')
                    ->label('Organization')
                    ->relationship('organization', 'name')
                    ->searchable(),
                SelectFilter::make('organization_id')
                    ->label('Organization ID')
                    ->relationship('organization', 'id')
                    ->searchable(),
            ])
            ->actions([
                Tables\Actions\EditAction::make(),
            ])
            ->bulkActions([
                Tables\Actions\BulkActionGroup::make([
                    Tables\Actions\DeleteBulkAction::make(),
                ]),
            ]);
    }

    public static function getRelations(): array
    {
        return [
            //
        ];
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\ListClients::route('/'),
            'create' => Pages\CreateClient::route('/create'),
            'edit' => Pages\EditClient::route('/{record}/edit'),
        ];
    }
}


================================================
FILE: app/Filament/Resources/FailedJobResource/Pages/ListFailedJobs.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources\FailedJobResource\Pages;

use App\Filament\Resources\FailedJobResource;
use App\Models\FailedJob;
use Filament\Actions\Action;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\ListRecords;
use Illuminate\Support\Facades\Artisan;

class ListFailedJobs extends ListRecords
{
    protected static string $resource = FailedJobResource::class;

    public function getHeaderActions(): array
    {
        return [
            Action::make('retry_all')
                ->icon('heroicon-o-arrow-path')
                ->label('Retry all')
                ->requiresConfirmation()
                ->action(function (): void {
                    Artisan::call('queue:retry all');
                    Notification::make()
                        ->title('All failed jobs have been pushed back onto the queue.')
                        ->success()
                        ->send();
                }),

            Action::make('delete_all')
                ->icon('heroicon-o-trash')
                ->label('Delete all')
                ->requiresConfirmation()
                ->color('danger')
                ->action(function (): void {
                    FailedJob::truncate();
                    Notification::make()
                        ->title('All failed jobs have been removed.')
                        ->success()
                        ->send();
                }),
        ];
    }
}


================================================
FILE: app/Filament/Resources/FailedJobResource/Pages/ViewFailedJobs.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources\FailedJobResource\Pages;

use App\Filament\Resources\FailedJobResource;
use Filament\Resources\Pages\ViewRecord;

class ViewFailedJobs extends ViewRecord
{
    protected static string $resource = FailedJobResource::class;
}


================================================
FILE: app/Filament/Resources/FailedJobResource.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources;

use App\Filament\Resources\FailedJobResource\Pages\ListFailedJobs;
use App\Filament\Resources\FailedJobResource\Pages\ViewFailedJobs;
use App\Models\FailedJob;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Notifications\Notification;
use Filament\Resources\Resource;
use Filament\Tables\Actions\Action;
use Filament\Tables\Actions\BulkAction;
use Filament\Tables\Actions\DeleteAction;
use Filament\Tables\Actions\DeleteBulkAction;
use Filament\Tables\Actions\ViewAction;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Artisan;
use Novadaemon\FilamentPrettyJson\Form\PrettyJsonField;

/**
 * @source https://gitlab.com/amvisor/filament-failed-jobs
 */
class FailedJobResource extends Resource
{
    protected static ?string $model = FailedJob::class;

    protected static ?string $navigationIcon = 'heroicon-o-exclamation-circle';

    protected static ?string $navigationGroup = 'System';

    public static function getNavigationBadge(): ?string
    {
        return (string) FailedJob::query()->count();
    }

    public static function form(Form $form): Form
    {
        return $form
            ->schema([
                TextInput::make('uuid')->disabled()->columnSpan(4),
                TextInput::make('failed_at')->disabled(),
                TextInput::make('id')->disabled(),
                TextInput::make('connection')->disabled(),
                TextInput::make('queue')->disabled(),

                // make text a little bit smaller because often a complete Stack Trace is shown:
                TextArea::make('exception')->disabled()->columnSpan(4)->extraInputAttributes(['style' => 'font-size: 80%;']),
                PrettyJsonField::make('payload')->disabled()->columnSpan(4),
            ])->columns(4);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->defaultSort('id', 'desc')
            ->columns([
                TextColumn::make('id')->sortable()->searchable()->toggleable(),
                TextColumn::make('failed_at')->sortable()->searchable(false)->toggleable(),
                TextColumn::make('exception')
                    ->sortable()
                    ->searchable()
                    ->toggleable()
                    ->wrap()
                    ->limit(200)
                    ->tooltip(fn (FailedJob $record) => "{$record->failed_at} UUID: {$record->uuid}; Connection: {$record->connection}; Queue: {$record->queue};"),
                TextColumn::make('uuid')->sortable()->searchable()->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('connection')->sortable()->searchable()->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('queue')->sortable()->searchable()->toggleable(isToggledHiddenByDefault: true),
            ])
            ->filters([])
            ->bulkActions([
                BulkAction::make('retry')
                    ->icon('heroicon-o-arrow-path')
                    ->label('Retry selected')
                    ->requiresConfirmation()
                    ->action(function (Collection $records): void {
                        /** @var FailedJob $record */
                        foreach ($records as $record) {
                            Artisan::call("queue:retry {$record->uuid}");
                        }
                        Notification::make()
                            ->title("{$records->count()} jobs have been pushed back onto the queue.")
                            ->success()
                            ->send();
                    }),
                DeleteBulkAction::make(),
            ])
            ->actions([
                DeleteAction::make(),
                ViewAction::make(),
                Action::make('retry')
                    ->icon('heroicon-o-arrow-path')
                    ->label('Retry')
                    ->requiresConfirmation()
                    ->action(function (FailedJob $record): void {
                        Artisan::call("queue:retry {$record->uuid}");
                        Notification::make()
                            ->title("The job with uuid '{$record->uuid}' has been pushed back onto the queue.")
                            ->success()
                            ->send();
                    }),
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => ListFailedJobs::route('/'),
            'view' => ViewFailedJobs::route('/{record}'),
        ];
    }
}


================================================
FILE: app/Filament/Resources/OrganizationInvitationResource/Pages/EditOrganizationInvitation.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources\OrganizationInvitationResource\Pages;

use App\Filament\Resources\OrganizationInvitationResource;
use Filament\Actions;
use Filament\Resources\Pages\EditRecord;

class EditOrganizationInvitation extends EditRecord
{
    protected static string $resource = OrganizationInvitationResource::class;

    protected function getHeaderActions(): array
    {
        return [
            Actions\DeleteAction::make()
                ->icon('heroicon-m-trash'),
        ];
    }
}


================================================
FILE: app/Filament/Resources/OrganizationInvitationResource/Pages/ListOrganizationInvitations.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources\OrganizationInvitationResource\Pages;

use App\Filament\Resources\OrganizationInvitationResource;
use Filament\Resources\Pages\ListRecords;

class ListOrganizationInvitations extends ListRecords
{
    protected static string $resource = OrganizationInvitationResource::class;

    protected function getHeaderActions(): array
    {
        return [
        ];
    }
}


================================================
FILE: app/Filament/Resources/OrganizationInvitationResource/Pages/ViewOrganizationInvitation.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources\OrganizationInvitationResource\Pages;

use App\Filament\Resources\OrganizationInvitationResource;
use Filament\Actions\EditAction;
use Filament\Resources\Pages\ViewRecord;

class ViewOrganizationInvitation extends ViewRecord
{
    protected static string $resource = OrganizationInvitationResource::class;

    protected function getHeaderActions(): array
    {
        return [
            EditAction::make('edit')
                ->icon('heroicon-s-pencil'),
        ];
    }
}


================================================
FILE: app/Filament/Resources/OrganizationInvitationResource.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources;

use App\Enums\Role;
use App\Filament\Resources\OrganizationInvitationResource\Pages;
use App\Models\OrganizationInvitation;
use App\Service\OrganizationInvitationService;
use Filament\Forms;
use Filament\Forms\Components\Select;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Support\Collection;

class OrganizationInvitationResource extends Resource
{
    protected static ?string $model = OrganizationInvitation::class;

    protected static ?string $label = 'Invitations';

    protected static ?string $navigationIcon = 'heroicon-o-user-plus';

    protected static ?string $navigationGroup = 'Users';

    protected static ?int $navigationSort = 9;

    public static function form(Form $form): Form
    {
        return $form
            ->columns(1)
            ->schema([
                Forms\Components\TextInput::make('email')
                    ->label('Email')
                    ->disabledOn(['edit'])
                    ->required(),
                Select::make('role')
                    ->options(Role::class),
                Forms\Components\Select::make('organization_id')
                    ->label('Organization')
                    ->relationship(name: 'organization', titleAttribute: 'name')
                    ->searchable(['name'])
                    ->disabledOn(['edit'])
                    ->required(),
                Forms\Components\DateTimePicker::make('created_at')
                    ->label('Created At')
                    ->hiddenOn(['create'])
                    ->disabled(),
                Forms\Components\DateTimePicker::make('updated_at')
                    ->label('Updated At')
                    ->hiddenOn(['create'])
                    ->disabled(),
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\Columns\TextColumn::make('organization.name')
                    ->searchable()
                    ->sortable(),
                Tables\Columns\TextColumn::make('email')
                    ->sortable(),
                Tables\Columns\TextColumn::make('role'),
                Tables\Columns\TextColumn::make('created_at')
                    ->label('Created At')
                    ->dateTime()
                    ->sortable(),
                Tables\Columns\TextColumn::make('updated_at')
                    ->label('Updated At')
                    ->dateTime()
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->defaultSort('created_at', 'desc')
            ->filters([
                //
            ])
            ->actions([
                Tables\Actions\EditAction::make(),
                Tables\Actions\DeleteAction::make(),
            ])
            ->bulkActions([
                Tables\Actions\BulkActionGroup::make([
                    Tables\Actions\BulkAction::make('resend')
                        ->label('Resend')
                        ->action(function (Collection $records): void {
                            foreach ($records as $organizationInvite) {
                                app(OrganizationInvitationService::class)->resend($organizationInvite);
                            }
                        }),
                ]),
            ]);
    }

    public static function getRelations(): array
    {
        return [
        ];
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\ListOrganizationInvitations::route('/'),
            'edit' => Pages\EditOrganizationInvitation::route('/{record}/edit'),
            'view' => Pages\ViewOrganizationInvitation::route('/{record}'),
        ];
    }
}


================================================
FILE: app/Filament/Resources/OrganizationResource/Actions/DeleteOrganization.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources\OrganizationResource\Actions;

use App\Exceptions\Api\ApiException;
use App\Models\Organization;
use App\Service\DeletionService;
use Filament\Actions\DeleteAction;
use Throwable;

class DeleteOrganization extends DeleteAction
{
    protected function setUp(): void
    {
        parent::setUp();
        $this->icon('heroicon-m-trash');
        $this->action(function (): void {
            $result = $this->process(function (Organization $record): bool {
                try {
                    $deletionService = app(DeletionService::class);
                    $deletionService->deleteOrganization($record);

                    return true;
                } catch (ApiException $exception) {
                    $this->failureNotificationTitle($exception->getTranslatedMessage());
                    report($exception);
                } catch (Throwable $exception) {
                    $this->failureNotificationTitle(__('exceptions.unknown_error_in_admin_panel'));
                    report($exception);
                }

                return false;
            });

            if (! $result) {
                $this->failure();

                return;
            }

            $this->success();
        });
    }
}


================================================
FILE: app/Filament/Resources/OrganizationResource/Pages/CreateOrganization.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources\OrganizationResource\Pages;

use App\Enums\Role;
use App\Filament\Resources\OrganizationResource;
use App\Models\Organization;
use Filament\Resources\Pages\CreateRecord;

class CreateOrganization extends CreateRecord
{
    protected static string $resource = OrganizationResource::class;

    protected function mutateFormDataBeforeCreate(array $data): array
    {
        $data['personal_team'] = false;

        return $data;
    }

    protected function afterCreate(): void
    {
        /** @var Organization $organization */
        $organization = $this->record;

        $user = $organization->owner;

        $organization->users()->attach(
            $user, [
                'role' => Role::Owner->value,
            ]
        );
    }
}


================================================
FILE: app/Filament/Resources/OrganizationResource/Pages/EditOrganization.php
================================================
<?php

declare(strict_types=1);

namespace App\Filament\Resources\OrganizationResource\Pages;

use App\Filament\Resources\OrganizationResource;
use Filament\Resources\Pages\EditRecord;

class EditOrganization extends EditRecord
{
    protected static string $resource = OrganizationResource::class;

    protected function getHeaderActions(): array
    {
        return [
            OrganizationResource\Actions\DeleteOrganization::make(),
        ];
    }
}


================================================
FILE: app/Filament/Resources/OrganizationResource/Pages/ListOrganizations.php
==========================
Download .txt
gitextract_ryuvl2mb/

├── .editorconfig
├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── 1_bug_report.yml
│   │   └── config.yml
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── build-onpremise.yml
│       ├── build-private.yml
│       ├── build-public.yml
│       ├── generate-api-docs.yml
│       ├── npm-build.yml
│       ├── npm-format-check.yml
│       ├── npm-lint.yml
│       ├── npm-publish-api.yml
│       ├── npm-publish-ui.yml
│       ├── npm-typecheck.yml
│       ├── phpstan.yml
│       ├── phpunit.yml
│       ├── pint.yml
│       └── playwright.yml
├── .gitignore
├── .prettierignore
├── .prettierrc.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── SECURITY.md
├── app/
│   ├── Actions/
│   │   ├── Fortify/
│   │   │   ├── CreateNewUser.php
│   │   │   ├── PasswordValidationRules.php
│   │   │   ├── ResetUserPassword.php
│   │   │   ├── UpdateUserPassword.php
│   │   │   └── UpdateUserProfileInformation.php
│   │   └── Jetstream/
│   │       ├── AddOrganizationMember.php
│   │       ├── CreateOrganization.php
│   │       ├── DeleteOrganization.php
│   │       ├── DeleteUser.php
│   │       ├── InviteOrganizationMember.php
│   │       ├── RemoveOrganizationMember.php
│   │       ├── UpdateMemberRole.php
│   │       ├── UpdateOrganization.php
│   │       └── ValidateOrganizationDeletion.php
│   ├── Console/
│   │   ├── Commands/
│   │   │   ├── Admin/
│   │   │   │   ├── OrganizationDeleteCommand.php
│   │   │   │   ├── UserCreateCommand.php
│   │   │   │   └── UserVerifyCommand.php
│   │   │   ├── Auth/
│   │   │   │   └── AuthSendReminderForExpiringApiTokensCommand.php
│   │   │   ├── Correction/
│   │   │   │   └── CorrectionPlaceholderMembersCommand.php
│   │   │   ├── Report/
│   │   │   │   └── ReportSetExpiredToPrivateCommand.php
│   │   │   ├── SelfHost/
│   │   │   │   ├── SelfHostCheckForUpdateCommand.php
│   │   │   │   ├── SelfHostDatabaseConsistency.php
│   │   │   │   ├── SelfHostGenerateKeysCommand.php
│   │   │   │   └── SelfHostTelemetryCommand.php
│   │   │   ├── Test/
│   │   │   │   ├── TestEmailCommand.php
│   │   │   │   ├── TestJobCommand.php
│   │   │   │   └── TestOutputCommand.php
│   │   │   └── TimeEntry/
│   │   │       └── TimeEntrySendStillRunningMailsCommand.php
│   │   └── Kernel.php
│   ├── Enums/
│   │   ├── CurrencyFormat.php
│   │   ├── DateFormat.php
│   │   ├── ExportFormat.php
│   │   ├── IntervalFormat.php
│   │   ├── NumberFormat.php
│   │   ├── Role.php
│   │   ├── TimeEntryAggregationType.php
│   │   ├── TimeEntryAggregationTypeInterval.php
│   │   ├── TimeEntryRoundingType.php
│   │   ├── TimeFormat.php
│   │   └── Weekday.php
│   ├── Events/
│   │   ├── AfterCreateOrganization.php
│   │   ├── BeforeOrganizationDeletion.php
│   │   ├── DatabaseSeederAfterSeed.php
│   │   ├── DatabaseSeederBeforeDelete.php
│   │   ├── MemberMadeToPlaceholder.php
│   │   ├── MemberRemoved.php
│   │   └── NewsletterRegistered.php
│   ├── Exceptions/
│   │   ├── Api/
│   │   │   ├── ApiException.php
│   │   │   ├── CanNotDeleteUserWhoIsOwnerOfOrganizationWithMultipleMembers.php
│   │   │   ├── CanNotRemoveOwnerFromOrganization.php
│   │   │   ├── ChangingRoleOfPlaceholderIsNotAllowed.php
│   │   │   ├── ChangingRoleToPlaceholderIsNotAllowed.php
│   │   │   ├── EntityStillInUseApiException.php
│   │   │   ├── FeatureIsNotAvailableInFreePlanApiException.php
│   │   │   ├── InactiveUserCanNotBeUsedApiException.php
│   │   │   ├── InvitationForTheEmailAlreadyExistsApiException.php
│   │   │   ├── OnlyOwnerCanChangeOwnership.php
│   │   │   ├── OnlyPlaceholdersCanBeMergedIntoAnotherMember.php
│   │   │   ├── OrganizationHasNoSubscriptionButMultipleMembersException.php
│   │   │   ├── OrganizationNeedsAtLeastOneOwner.php
│   │   │   ├── OverlappingTimeEntryApiException.php
│   │   │   ├── PdfRendererIsNotConfiguredException.php
│   │   │   ├── PersonalAccessClientIsNotConfiguredException.php
│   │   │   ├── ThisPlaceholderCanNotBeInvitedUseTheMergeToolInsteadException.php
│   │   │   ├── TimeEntryCanNotBeRestartedApiException.php
│   │   │   ├── TimeEntryStillRunningApiException.php
│   │   │   ├── UserIsAlreadyMemberOfOrganizationApiException.php
│   │   │   ├── UserIsAlreadyMemberOfProjectApiException.php
│   │   │   └── UserNotPlaceholderApiException.php
│   │   ├── Handler.php
│   │   └── MovedToApiException.php
│   ├── Extensions/
│   │   ├── Auditing/
│   │   │   └── Resolvers/
│   │   │       └── CustomIpAddressResolver.php
│   │   ├── Fortify/
│   │   │   ├── CustomLoginResponse.php
│   │   │   └── CustomTwoFactorLoginResponse.php
│   │   └── Scramble/
│   │       ├── ApiExceptionTypeToSchema.php
│   │       └── PaginatedResourceCollectionTypeToSchema.php
│   ├── Filament/
│   │   ├── Resources/
│   │   │   ├── AuditResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── CreateAudit.php
│   │   │   │       ├── ListAudits.php
│   │   │   │       └── ViewAudit.php
│   │   │   ├── AuditResource.php
│   │   │   ├── ClientResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── CreateClient.php
│   │   │   │       ├── EditClient.php
│   │   │   │       └── ListClients.php
│   │   │   ├── ClientResource.php
│   │   │   ├── FailedJobResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── ListFailedJobs.php
│   │   │   │       └── ViewFailedJobs.php
│   │   │   ├── FailedJobResource.php
│   │   │   ├── OrganizationInvitationResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── EditOrganizationInvitation.php
│   │   │   │       ├── ListOrganizationInvitations.php
│   │   │   │       └── ViewOrganizationInvitation.php
│   │   │   ├── OrganizationInvitationResource.php
│   │   │   ├── OrganizationResource/
│   │   │   │   ├── Actions/
│   │   │   │   │   └── DeleteOrganization.php
│   │   │   │   ├── Pages/
│   │   │   │   │   ├── CreateOrganization.php
│   │   │   │   │   ├── EditOrganization.php
│   │   │   │   │   ├── ListOrganizations.php
│   │   │   │   │   └── ViewOrganization.php
│   │   │   │   └── RelationManagers/
│   │   │   │       ├── InvitationsRelationManager.php
│   │   │   │       └── UsersRelationManager.php
│   │   │   ├── OrganizationResource.php
│   │   │   ├── ProjectMemberResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── CreateProjectMember.php
│   │   │   │       ├── EditProjectMember.php
│   │   │   │       ├── ListProjectMembers.php
│   │   │   │       └── ViewProjectMembers.php
│   │   │   ├── ProjectMemberResource.php
│   │   │   ├── ProjectResource/
│   │   │   │   ├── Pages/
│   │   │   │   │   ├── CreateProject.php
│   │   │   │   │   ├── EditProject.php
│   │   │   │   │   └── ListProjects.php
│   │   │   │   └── RelationManagers/
│   │   │   │       └── ProjectMembersRelationManager.php
│   │   │   ├── ProjectResource.php
│   │   │   ├── ReportResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── EditReport.php
│   │   │   │       ├── ListReports.php
│   │   │   │       └── ViewReport.php
│   │   │   ├── ReportResource.php
│   │   │   ├── TagResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── CreateTag.php
│   │   │   │       ├── EditTag.php
│   │   │   │       └── ListTags.php
│   │   │   ├── TagResource.php
│   │   │   ├── TaskResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── CreateTask.php
│   │   │   │       ├── EditTask.php
│   │   │   │       └── ListTasks.php
│   │   │   ├── TaskResource.php
│   │   │   ├── TimeEntryResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── CreateTimeEntry.php
│   │   │   │       ├── EditTimeEntry.php
│   │   │   │       └── ListTimeEntries.php
│   │   │   ├── TimeEntryResource.php
│   │   │   ├── TokenResource/
│   │   │   │   └── Pages/
│   │   │   │       ├── ListTokens.php
│   │   │   │       └── ViewToken.php
│   │   │   ├── TokenResource.php
│   │   │   ├── UserResource/
│   │   │   │   ├── Actions/
│   │   │   │   │   └── DeleteUser.php
│   │   │   │   ├── Pages/
│   │   │   │   │   ├── CreateUser.php
│   │   │   │   │   ├── EditUser.php
│   │   │   │   │   ├── ListUsers.php
│   │   │   │   │   └── ViewUser.php
│   │   │   │   └── RelationManagers/
│   │   │   │       ├── OrganizationsRelationManager.php
│   │   │   │       └── OwnedOrganizationsRelationManager.php
│   │   │   └── UserResource.php
│   │   └── Widgets/
│   │       ├── ActiveUserOverview.php
│   │       ├── ServerOverview.php
│   │       ├── TimeEntriesCreated.php
│   │       ├── TimeEntriesImported.php
│   │       └── UserRegistrations.php
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── Api/
│   │   │   │   └── V1/
│   │   │   │       ├── ApiTokenController.php
│   │   │   │       ├── ChartController.php
│   │   │   │       ├── ClientController.php
│   │   │   │       ├── Controller.php
│   │   │   │       ├── CurrencyController.php
│   │   │   │       ├── ExportController.php
│   │   │   │       ├── ImportController.php
│   │   │   │       ├── InvitationController.php
│   │   │   │       ├── MemberController.php
│   │   │   │       ├── OrganizationController.php
│   │   │   │       ├── ProjectController.php
│   │   │   │       ├── ProjectMemberController.php
│   │   │   │       ├── Public/
│   │   │   │       │   └── ReportController.php
│   │   │   │       ├── ReportController.php
│   │   │   │       ├── TagController.php
│   │   │   │       ├── TaskController.php
│   │   │   │       ├── TimeEntryController.php
│   │   │   │       ├── UserController.php
│   │   │   │       ├── UserMembershipController.php
│   │   │   │       └── UserTimeEntryController.php
│   │   │   ├── Controller.php
│   │   │   └── Web/
│   │   │       ├── Controller.php
│   │   │       ├── DashboardController.php
│   │   │       ├── HealthCheckController.php
│   │   │       └── HomeController.php
│   │   ├── Kernel.php
│   │   ├── Middleware/
│   │   │   ├── Authenticate.php
│   │   │   ├── CheckOrganizationBlocked.php
│   │   │   ├── EncryptCookies.php
│   │   │   ├── EnsureEmailIsVerified.php
│   │   │   ├── ForceHttps.php
│   │   │   ├── ForceJsonResponse.php
│   │   │   ├── HandleInertiaRequests.php
│   │   │   ├── PreventRequestsDuringMaintenance.php
│   │   │   ├── RedirectIfAuthenticated.php
│   │   │   ├── ShareInertiaData.php
│   │   │   ├── TrimStrings.php
│   │   │   ├── TrustProxies.php
│   │   │   ├── ValidateSignature.php
│   │   │   └── VerifyCsrfToken.php
│   │   ├── Requests/
│   │   │   └── V1/
│   │   │       ├── ApiToken/
│   │   │       │   └── ApiTokenStoreRequest.php
│   │   │       ├── BaseFormRequest.php
│   │   │       ├── Client/
│   │   │       │   ├── ClientIndexRequest.php
│   │   │       │   ├── ClientStoreRequest.php
│   │   │       │   └── ClientUpdateRequest.php
│   │   │       ├── Import/
│   │   │       │   └── ImportRequest.php
│   │   │       ├── Invitation/
│   │   │       │   ├── InvitationIndexRequest.php
│   │   │       │   └── InvitationStoreRequest.php
│   │   │       ├── Member/
│   │   │       │   ├── MemberDestroyRequest.php
│   │   │       │   ├── MemberIndexRequest.php
│   │   │       │   ├── MemberMergeIntoRequest.php
│   │   │       │   └── MemberUpdateRequest.php
│   │   │       ├── Organization/
│   │   │       │   └── OrganizationUpdateRequest.php
│   │   │       ├── Project/
│   │   │       │   ├── ProjectIndexRequest.php
│   │   │       │   ├── ProjectStoreRequest.php
│   │   │       │   └── ProjectUpdateRequest.php
│   │   │       ├── ProjectMember/
│   │   │       │   ├── ProjectMemberIndexRequest.php
│   │   │       │   ├── ProjectMemberStoreRequest.php
│   │   │       │   └── ProjectMemberUpdateRequest.php
│   │   │       ├── Report/
│   │   │       │   ├── ReportIndexRequest.php
│   │   │       │   ├── ReportStoreRequest.php
│   │   │       │   └── ReportUpdateRequest.php
│   │   │       ├── Tag/
│   │   │       │   ├── TagIndexRequest.php
│   │   │       │   ├── TagStoreRequest.php
│   │   │       │   └── TagUpdateRequest.php
│   │   │       ├── Task/
│   │   │       │   ├── TaskIndexRequest.php
│   │   │       │   ├── TaskStoreRequest.php
│   │   │       │   └── TaskUpdateRequest.php
│   │   │       └── TimeEntry/
│   │   │           ├── TimeEntryAggregateExportRequest.php
│   │   │           ├── TimeEntryAggregateRequest.php
│   │   │           ├── TimeEntryDestroyMultipleRequest.php
│   │   │           ├── TimeEntryIndexExportRequest.php
│   │   │           ├── TimeEntryIndexRequest.php
│   │   │           ├── TimeEntryStoreRequest.php
│   │   │           ├── TimeEntryUpdateMultipleRequest.php
│   │   │           └── TimeEntryUpdateRequest.php
│   │   └── Resources/
│   │       ├── PaginatedResourceCollection.php
│   │       └── V1/
│   │           ├── ApiToken/
│   │           │   ├── ApiTokenCollection.php
│   │           │   ├── ApiTokenResource.php
│   │           │   └── ApiTokenWithAccessTokenResource.php
│   │           ├── BaseResource.php
│   │           ├── Client/
│   │           │   ├── ClientCollection.php
│   │           │   └── ClientResource.php
│   │           ├── Invitation/
│   │           │   ├── InvitationCollection.php
│   │           │   └── InvitationResource.php
│   │           ├── Member/
│   │           │   ├── MemberCollection.php
│   │           │   ├── MemberResource.php
│   │           │   ├── PersonalMembershipCollection.php
│   │           │   └── PersonalMembershipResource.php
│   │           ├── Organization/
│   │           │   └── OrganizationResource.php
│   │           ├── Project/
│   │           │   ├── ProjectCollection.php
│   │           │   └── ProjectResource.php
│   │           ├── ProjectMember/
│   │           │   ├── ProjectMemberCollection.php
│   │           │   └── ProjectMemberResource.php
│   │           ├── Report/
│   │           │   ├── DetailedReportResource.php
│   │           │   ├── DetailedWithDataReportResource.php
│   │           │   ├── ReportCollection.php
│   │           │   └── ReportResource.php
│   │           ├── Tag/
│   │           │   ├── TagCollection.php
│   │           │   └── TagResource.php
│   │           ├── Task/
│   │           │   ├── TaskCollection.php
│   │           │   └── TaskResource.php
│   │           ├── TimeEntry/
│   │           │   ├── TimeEntryCollection.php
│   │           │   └── TimeEntryResource.php
│   │           └── User/
│   │               └── UserResource.php
│   ├── Jobs/
│   │   ├── RecalculateSpentTimeForProject.php
│   │   ├── RecalculateSpentTimeForTask.php
│   │   └── Test/
│   │       └── TestJob.php
│   ├── Listeners/
│   │   └── RemovePlaceholder.php
│   ├── Mail/
│   │   ├── AuthApiTokenExpirationReminderMail.php
│   │   ├── AuthApiTokenExpiredMail.php
│   │   ├── OrganizationInvitationMail.php
│   │   └── TimeEntryStillRunningMail.php
│   ├── Models/
│   │   ├── Audit.php
│   │   ├── Client.php
│   │   ├── Concerns/
│   │   │   ├── CustomAuditable.php
│   │   │   └── HasUuids.php
│   │   ├── FailedJob.php
│   │   ├── Member.php
│   │   ├── Organization.php
│   │   ├── OrganizationInvitation.php
│   │   ├── Passport/
│   │   │   ├── AuthCode.php
│   │   │   ├── Client.php
│   │   │   ├── RefreshToken.php
│   │   │   └── Token.php
│   │   ├── Project.php
│   │   ├── ProjectMember.php
│   │   ├── Report.php
│   │   ├── Tag.php
│   │   ├── Task.php
│   │   ├── TimeEntry.php
│   │   └── User.php
│   ├── Policies/
│   │   └── OrganizationPolicy.php
│   ├── Providers/
│   │   ├── AppServiceProvider.php
│   │   ├── AuthServiceProvider.php
│   │   ├── EventServiceProvider.php
│   │   ├── Filament/
│   │   │   └── AdminPanelProvider.php
│   │   ├── FortifyServiceProvider.php
│   │   ├── JetstreamServiceProvider.php
│   │   ├── RouteServiceProvider.php
│   │   └── TelescopeServiceProvider.php
│   ├── Rules/
│   │   ├── ColorRule.php
│   │   └── CurrencyRule.php
│   └── Service/
│       ├── ApiService.php
│       ├── BillableRateService.php
│       ├── BillingContract.php
│       ├── ColorService.php
│       ├── CurrencyService.php
│       ├── DashboardService.php
│       ├── DeletionService.php
│       ├── Dto/
│       │   └── ReportPropertiesDto.php
│       ├── Export/
│       │   ├── ExportException.php
│       │   └── ExportService.php
│       ├── Import/
│       │   ├── ImportDatabaseHelper.php
│       │   ├── ImportService.php
│       │   └── Importers/
│       │       ├── ClockifyProjectsImporter.php
│       │       ├── ClockifyTimeEntriesImporter.php
│       │       ├── DefaultImporter.php
│       │       ├── GenericProjectsImporter.php
│       │       ├── GenericTimeEntriesImporter.php
│       │       ├── HarvestClientsImporter.php
│       │       ├── HarvestProjectsImporter.php
│       │       ├── HarvestTimeEntriesImporter.php
│       │       ├── ImportException.php
│       │       ├── ImporterContract.php
│       │       ├── ImporterProvider.php
│       │       ├── ReportDto.php
│       │       ├── SolidtimeImporter.php
│       │       ├── TogglDataImporter.php
│       │       └── TogglTimeEntriesImporter.php
│       ├── IntervalService.php
│       ├── InvitationService.php
│       ├── IpLookup/
│       │   ├── IpLookupResponseDto.php
│       │   ├── IpLookupServiceContract.php
│       │   └── NoIpLookupService.php
│       ├── LocalizationService.php
│       ├── MemberService.php
│       ├── OrganizationInvitationService.php
│       ├── OrganizationService.php
│       ├── PermissionStore.php
│       ├── ReportExport/
│       │   ├── CsvExport.php
│       │   ├── TimeEntriesDetailedCsvExport.php
│       │   ├── TimeEntriesDetailedExport.php
│       │   └── TimeEntriesReportExport.php
│       ├── ReportService.php
│       ├── TimeEntryAggregationService.php
│       ├── TimeEntryFilter.php
│       ├── TimeEntryService.php
│       ├── TimezoneService.php
│       └── UserService.php
├── artisan
├── bootstrap/
│   ├── app.php
│   └── cache/
│       └── .gitignore
├── components.json
├── composer.json
├── config/
│   ├── app.php
│   ├── audit.php
│   ├── auth.php
│   ├── broadcasting.php
│   ├── cache.php
│   ├── cors.php
│   ├── database.php
│   ├── excel.php
│   ├── filament.php
│   ├── filesystems.php
│   ├── fortify.php
│   ├── hashing.php
│   ├── jetstream.php
│   ├── logging.php
│   ├── mail.php
│   ├── modules.php
│   ├── octane.php
│   ├── passport.php
│   ├── queue.php
│   ├── scheduling.php
│   ├── scramble.php
│   ├── services.php
│   ├── session.php
│   ├── telescope.php
│   ├── trustedproxy.php
│   └── view.php
├── database/
│   ├── .gitignore
│   ├── factories/
│   │   ├── AuditFactory.php
│   │   ├── ClientFactory.php
│   │   ├── FailedJobFactory.php
│   │   ├── MemberFactory.php
│   │   ├── OrganizationFactory.php
│   │   ├── OrganizationInvitationFactory.php
│   │   ├── Passport/
│   │   │   ├── ClientFactory.php
│   │   │   └── TokenFactory.php
│   │   ├── ProjectFactory.php
│   │   ├── ProjectMemberFactory.php
│   │   ├── ReportFactory.php
│   │   ├── TagFactory.php
│   │   ├── TaskFactory.php
│   │   ├── TimeEntryFactory.php
│   │   └── UserFactory.php
│   ├── migrations/
│   │   ├── 2014_10_12_000000_create_users_table.php
│   │   ├── 2014_10_12_100000_create_password_reset_tokens_table.php
│   │   ├── 2014_10_12_200000_add_two_factor_columns_to_users_table.php
│   │   ├── 2016_06_01_000001_create_oauth_auth_codes_table.php
│   │   ├── 2016_06_01_000002_create_oauth_access_tokens_table.php
│   │   ├── 2016_06_01_000003_create_oauth_refresh_tokens_table.php
│   │   ├── 2016_06_01_000004_create_oauth_clients_table.php
│   │   ├── 2016_06_01_000005_create_oauth_personal_access_clients_table.php
│   │   ├── 2018_08_08_100000_create_telescope_entries_table.php
│   │   ├── 2019_08_19_000000_create_failed_jobs_table.php
│   │   ├── 2019_12_14_000001_create_personal_access_tokens_table.php
│   │   ├── 2020_05_21_100000_create_organizations_table.php
│   │   ├── 2020_05_21_200000_create_organization_user_table.php
│   │   ├── 2020_05_21_300000_create_organization_invitations_table.php
│   │   ├── 2024_01_16_161030_create_sessions_table.php
│   │   ├── 2024_01_20_110218_create_clients_table.php
│   │   ├── 2024_01_20_110439_create_projects_table.php
│   │   ├── 2024_01_20_110444_create_tasks_table.php
│   │   ├── 2024_01_20_110452_create_tags_table.php
│   │   ├── 2024_01_20_110837_create_time_entries_table.php
│   │   ├── 2024_03_26_171253_create_project_members_table.php
│   │   ├── 2024_04_11_150130_create_jobs_table.php
│   │   ├── 2024_04_12_095010_create_cache_table.php
│   │   ├── 2024_05_07_134711_move_from_user_id_to_member_id_in_project_members_table.php
│   │   ├── 2024_05_07_141842_move_from_user_id_to_member_id_in_time_entries_table.php
│   │   ├── 2024_05_13_171020_rename_table_organization_user_to_members.php
│   │   ├── 2024_05_22_151226_add_client_id_to_time_entries_table.php
│   │   ├── 2024_05_30_175801_add_is_billable_column_to_projects_table.php
│   │   ├── 2024_05_30_175825_add_is_imported_column_to_time_entries_table.php
│   │   ├── 2024_06_01_000001_create_oauth_device_codes_table.php
│   │   ├── 2024_06_07_113443_change_member_id_foreign_keys_to_restrict_on_delete.php
│   │   ├── 2024_06_10_161831_reset_billable_rates_with_zero_as_value.php
│   │   ├── 2024_06_21_122754_add_is_archived_columns_to_projects_and_clients_table.php
│   │   ├── 2024_06_24_114433_add_done_at_to_tasks_table.php
│   │   ├── 2024_07_02_134307_add_estimated_time_to_projects_and_tasks_table.php
│   │   ├── 2024_07_03_145445_change_data_type_of_id_column_in_failed_jobs_table.php
│   │   ├── 2024_07_18_080906_add_still_active_email_sent_at_to_time_entries_table.php
│   │   ├── 2024_08_01_104840_create_reports_table.php
│   │   ├── 2024_09_02_094105_create_audits_table.php
│   │   ├── 2024_09_18_120203_add_spent_time_to_projects_and_tasks_table.php
│   │   ├── 2024_10_01_143608_add_employees_can_see_billable_rates_to_organizations_table.php
│   │   ├── 2024_11_04_164807_add_foreign_key_to_organizations_and_members_table.php
│   │   ├── 2024_11_04_170614_add_foreign_keys_to_oauth_tables.php
│   │   ├── 2025_04_03_101827_add_localization_columns_to_organizations_table.php
│   │   ├── 2025_04_25_202047_change_data_type_for_spent_time_columns.php
│   │   ├── 2025_05_06_152804_fix_typos_in_organizations_table_format_columns.php
│   │   ├── 2025_05_16_075757_add_foreign_key_for_current_team_id_in_users_table.php
│   │   ├── 2025_06_30_095942_remove_oauth_personal_access_clients_table.php
│   │   ├── 2025_06_30_132538_update_oauth_clients_table.php
│   │   ├── 2025_07_15_105949_hash_oauth_clients.php
│   │   ├── 2025_07_17_104903_add_reminder_sent_at_to_oauth_access_tokens_table.php
│   │   ├── 2025_10_02_000001_add_prevent_overlapping_time_entries_to_organizations_table.php
│   │   ├── 2025_10_16_000001_extend_time_entry_description.php
│   │   └── 2025_10_24_120845_add_employees_can_manage_tasks_to_organizations_table.php
│   ├── schema/
│   │   └── pgsql_test-schema.sql
│   └── seeders/
│       └── DatabaseSeeder.php
├── docker/
│   ├── local/
│   │   ├── 8.3/
│   │   │   ├── Dockerfile
│   │   │   ├── php.ini
│   │   │   ├── start-container
│   │   │   └── supervisord.conf
│   │   ├── minio/
│   │   │   └── create_bucket.sh
│   │   └── pgsql/
│   │       └── create-testing-database.sql
│   └── prod/
│       ├── Dockerfile
│       ├── LICENSE
│       └── deployment/
│           ├── healthcheck
│           ├── octane/
│           │   └── FrankenPHP/
│           │       ├── Caddyfile
│           │       └── supervisord.frankenphp.conf
│           ├── php.ini
│           ├── start-container
│           ├── supervisord.conf
│           ├── supervisord.horizon.conf
│           ├── supervisord.reverb.conf
│           ├── supervisord.scheduler.conf
│           └── supervisord.worker.conf
├── docker-compose.yml
├── e2e/
│   ├── auth.spec.ts
│   ├── calendar-settings.spec.ts
│   ├── calendar.spec.ts
│   ├── clients.spec.ts
│   ├── command-palette.spec.ts
│   ├── dashboard.spec.ts
│   ├── import-export.spec.ts
│   ├── members.spec.ts
│   ├── organization.spec.ts
│   ├── profile.spec.ts
│   ├── project-members.spec.ts
│   ├── projects.spec.ts
│   ├── reporting-detailed.spec.ts
│   ├── reporting.spec.ts
│   ├── shared-reports.spec.ts
│   ├── tags.spec.ts
│   ├── tasks.spec.ts
│   ├── time.spec.ts
│   ├── timetracker.spec.ts
│   └── utils/
│       ├── api.ts
│       ├── currentTimeEntry.ts
│       ├── mailpit.ts
│       ├── members.ts
│       ├── money.ts
│       ├── reporting.ts
│       ├── table.ts
│       └── tags.ts
├── eslint.config.mjs
├── jsconfig.json
├── lang/
│   └── en/
│       ├── auth.php
│       ├── enum.php
│       ├── exceptions.php
│       ├── importer.php
│       ├── pagination.php
│       ├── passwords.php
│       └── validation.php
├── openapi.json
├── package.json
├── phpstan.neon
├── phpunit.xml
├── pint.json
├── playwright/
│   ├── config.ts
│   └── fixtures.ts
├── playwright.config.ts
├── postcss.config.js
├── public/
│   ├── .htaccess
│   ├── desktop-version/
│   │   ├── latest-linux.yml
│   │   ├── latest-mac.yml
│   │   └── latest.yml
│   ├── favicons/
│   │   ├── browserconfig.xml
│   │   └── site.webmanifest
│   ├── index.php
│   ├── robots.txt
│   └── security.txt
├── resources/
│   ├── css/
│   │   ├── app.css
│   │   └── filament/
│   │       └── admin/
│   │           ├── tailwind.config.js
│   │           └── theme.css
│   ├── js/
│   │   ├── Components/
│   │   │   ├── ActionMessage.vue
│   │   │   ├── ActionSection.vue
│   │   │   ├── ApplicationLogo.vue
│   │   │   ├── ApplicationMark.vue
│   │   │   ├── AuthenticationCard.vue
│   │   │   ├── AuthenticationCardLogo.vue
│   │   │   ├── Banner.vue
│   │   │   ├── Billing/
│   │   │   │   └── BillingBanner.vue
│   │   │   ├── CommandPalette/
│   │   │   │   ├── CommandPaletteProvider.vue
│   │   │   │   └── index.ts
│   │   │   ├── Common/
│   │   │   │   ├── Card.vue
│   │   │   │   ├── Client/
│   │   │   │   │   ├── ClientCreateModal.vue
│   │   │   │   │   ├── ClientEditModal.vue
│   │   │   │   │   ├── ClientMoreOptionsDropdown.vue
│   │   │   │   │   ├── ClientMultiselectDropdown.vue
│   │   │   │   │   ├── ClientTable.vue
│   │   │   │   │   ├── ClientTableHeading.vue
│   │   │   │   │   └── ClientTableRow.vue
│   │   │   │   ├── Invitation/
│   │   │   │   │   ├── InvitationMoreOptionsDropdown.vue
│   │   │   │   │   ├── InvitationTable.vue
│   │   │   │   │   ├── InvitationTableHeading.vue
│   │   │   │   │   └── InvitationTableRow.vue
│   │   │   │   ├── Member/
│   │   │   │   │   ├── MemberBillableRateModal.vue
│   │   │   │   │   ├── MemberBillableSelect.vue
│   │   │   │   │   ├── MemberCombobox.vue
│   │   │   │   │   ├── MemberDeleteModal.vue
│   │   │   │   │   ├── MemberEditModal.vue
│   │   │   │   │   ├── MemberInviteModal.vue
│   │   │   │   │   ├── MemberMakePlaceholderModal.vue
│   │   │   │   │   ├── MemberMergeModal.vue
│   │   │   │   │   ├── MemberMoreOptionsDropdown.vue
│   │   │   │   │   ├── MemberMultiselectDropdown.vue
│   │   │   │   │   ├── MemberOwnershipTransferConfirmModal.vue
│   │   │   │   │   ├── MemberRoleSelect.vue
│   │   │   │   │   ├── MemberTable.vue
│   │   │   │   │   ├── MemberTableHeading.vue
│   │   │   │   │   └── MemberTableRow.vue
│   │   │   │   ├── Notification/
│   │   │   │   │   └── Notification.vue
│   │   │   │   ├── Organization/
│   │   │   │   │   └── OrganizationBillableRateModal.vue
│   │   │   │   ├── PageTitle.vue
│   │   │   │   ├── Project/
│   │   │   │   │   ├── BaseFilterBadge.vue
│   │   │   │   │   ├── ProjectClientFilterBadge.vue
│   │   │   │   │   ├── ProjectDropdown.vue
│   │   │   │   │   ├── ProjectEditModal.vue
│   │   │   │   │   ├── ProjectMoreOptionsDropdown.vue
│   │   │   │   │   ├── ProjectMultiselectDropdown.vue
│   │   │   │   │   ├── ProjectStatusFilterBadge.vue
│   │   │   │   │   ├── ProjectTable.vue
│   │   │   │   │   ├── ProjectTableHeading.vue
│   │   │   │   │   ├── ProjectTableRow.vue
│   │   │   │   │   ├── ProjectsFilterDropdown.vue
│   │   │   │   │   └── constants.ts
│   │   │   │   ├── ProjectMember/
│   │   │   │   │   ├── ProjectMemberBillableRateModal.vue
│   │   │   │   │   ├── ProjectMemberCreateModal.vue
│   │   │   │   │   ├── ProjectMemberEditModal.vue
│   │   │   │   │   ├── ProjectMemberMoreOptionsDropdown.vue
│   │   │   │   │   ├── ProjectMemberTable.vue
│   │   │   │   │   ├── ProjectMemberTableHeading.vue
│   │   │   │   │   └── ProjectMemberTableRow.vue
│   │   │   │   ├── Report/
│   │   │   │   │   ├── ReportCreateModal.vue
│   │   │   │   │   ├── ReportEditModal.vue
│   │   │   │   │   ├── ReportMoreOptionsDropdown.vue
│   │   │   │   │   ├── ReportSaveButton.vue
│   │   │   │   │   ├── ReportTable.vue
│   │   │   │   │   ├── ReportTableHeading.vue
│   │   │   │   │   └── ReportTableRow.vue
│   │   │   │   ├── Reporting/
│   │   │   │   │   ├── ReportingChart.vue
│   │   │   │   │   ├── ReportingExportButton.vue
│   │   │   │   │   ├── ReportingExportModal.vue
│   │   │   │   │   ├── ReportingFilterBadge.vue
│   │   │   │   │   ├── ReportingFilterBar.vue
│   │   │   │   │   ├── ReportingGroupBySelect.vue
│   │   │   │   │   ├── ReportingOverview.vue
│   │   │   │   │   ├── ReportingPieChart.vue
│   │   │   │   │   ├── ReportingRoundingControls.vue
│   │   │   │   │   ├── ReportingRow.vue
│   │   │   │   │   └── ReportingTabNavbar.vue
│   │   │   │   ├── StatCard.vue
│   │   │   │   ├── TabBar/
│   │   │   │   │   ├── TabBar.vue
│   │   │   │   │   └── TabBarItem.vue
│   │   │   │   ├── TableHeading.vue
│   │   │   │   ├── Tag/
│   │   │   │   │   ├── TagEditModal.vue
│   │   │   │   │   ├── TagMoreOptionsDropdown.vue
│   │   │   │   │   ├── TagTable.vue
│   │   │   │   │   ├── TagTableHeading.vue
│   │   │   │   │   └── TagTableRow.vue
│   │   │   │   ├── Task/
│   │   │   │   │   ├── TaskCreateModal.vue
│   │   │   │   │   ├── TaskEditModal.vue
│   │   │   │   │   ├── TaskMoreOptionsDropdown.vue
│   │   │   │   │   ├── TaskMultiselectDropdown.vue
│   │   │   │   │   ├── TaskTable.vue
│   │   │   │   │   ├── TaskTableHeading.vue
│   │   │   │   │   └── TaskTableRow.vue
│   │   │   │   ├── UpgradeBadge.vue
│   │   │   │   ├── UpgradeModal.vue
│   │   │   │   └── User/
│   │   │   │       └── UserTimezoneMismatchModal.vue
│   │   │   ├── ConfirmationModal.vue
│   │   │   ├── ConfirmsPassword.vue
│   │   │   ├── CurrentSidebarTimer.vue
│   │   │   ├── Dashboard/
│   │   │   │   ├── ActivityGraphCard.vue
│   │   │   │   ├── DashboardCard.vue
│   │   │   │   ├── DayOverviewCardChart.vue
│   │   │   │   ├── DayOverviewCardEntry.vue
│   │   │   │   ├── LastSevenDaysCard.vue
│   │   │   │   ├── ProjectsChartCard.vue
│   │   │   │   ├── RecentlyTrackedTasksCard.vue
│   │   │   │   ├── RecentlyTrackedTasksCardEntry.vue
│   │   │   │   ├── TeamActivityCard.vue
│   │   │   │   ├── TeamActivityCardEntry.vue
│   │   │   │   ├── ThisWeekOverview.vue
│   │   │   │   └── ThisWeekReportingTable.vue
│   │   │   ├── DropdownLink.vue
│   │   │   ├── FormSection.vue
│   │   │   ├── NavLink.vue
│   │   │   ├── NavigationSidebarItem.vue
│   │   │   ├── NavigationSidebarLink.vue
│   │   │   ├── NotificationContainer.vue
│   │   │   ├── OrganizationSwitcher.vue
│   │   │   ├── ResponsiveNavLink.vue
│   │   │   ├── SectionBorder.vue
│   │   │   ├── SectionTitle.vue
│   │   │   ├── TableRow.vue
│   │   │   ├── TimeTracker.vue
│   │   │   ├── UpdateSidebarNotification.vue
│   │   │   ├── UserSettingsIcon.vue
│   │   │   └── ui/
│   │   │       ├── alert-dialog/
│   │   │       │   ├── AlertDialog.vue
│   │   │       │   ├── AlertDialogAction.vue
│   │   │       │   ├── AlertDialogCancel.vue
│   │   │       │   ├── AlertDialogContent.vue
│   │   │       │   ├── AlertDialogDescription.vue
│   │   │       │   ├── AlertDialogFooter.vue
│   │   │       │   ├── AlertDialogHeader.vue
│   │   │       │   ├── AlertDialogTitle.vue
│   │   │       │   ├── AlertDialogTrigger.vue
│   │   │       │   └── index.ts
│   │   │       ├── calendar/
│   │   │       │   ├── Calendar.vue
│   │   │       │   ├── CalendarCell.vue
│   │   │       │   ├── CalendarCellTrigger.vue
│   │   │       │   ├── CalendarDateInput.vue
│   │   │       │   ├── CalendarGrid.vue
│   │   │       │   ├── CalendarGridBody.vue
│   │   │       │   ├── CalendarGridHead.vue
│   │   │       │   ├── CalendarGridRow.vue
│   │   │       │   ├── CalendarHeadCell.vue
│   │   │       │   ├── CalendarHeader.vue
│   │   │       │   ├── CalendarHeading.vue
│   │   │       │   ├── CalendarNextButton.vue
│   │   │       │   ├── CalendarPrevButton.vue
│   │   │       │   └── index.ts
│   │   │       ├── dialog/
│   │   │       │   ├── Dialog.vue
│   │   │       │   ├── DialogClose.vue
│   │   │       │   ├── DialogContent.vue
│   │   │       │   ├── DialogDescription.vue
│   │   │       │   ├── DialogFooter.vue
│   │   │       │   ├── DialogHeader.vue
│   │   │       │   ├── DialogScrollContent.vue
│   │   │       │   ├── DialogTitle.vue
│   │   │       │   ├── DialogTrigger.vue
│   │   │       │   └── index.ts
│   │   │       ├── dropdown-menu/
│   │   │       │   ├── DropdownMenu.vue
│   │   │       │   ├── DropdownMenuCheckboxItem.vue
│   │   │       │   ├── DropdownMenuContent.vue
│   │   │       │   ├── DropdownMenuGroup.vue
│   │   │       │   ├── DropdownMenuItem.vue
│   │   │       │   ├── DropdownMenuLabel.vue
│   │   │       │   ├── DropdownMenuRadioGroup.vue
│   │   │       │   ├── DropdownMenuRadioItem.vue
│   │   │       │   ├── DropdownMenuSeparator.vue
│   │   │       │   ├── DropdownMenuShortcut.vue
│   │   │       │   ├── DropdownMenuSub.vue
│   │   │       │   ├── DropdownMenuSubContent.vue
│   │   │       │   ├── DropdownMenuSubTrigger.vue
│   │   │       │   ├── DropdownMenuTrigger.vue
│   │   │       │   └── index.ts
│   │   │       ├── label/
│   │   │       │   ├── Label.vue
│   │   │       │   └── index.ts
│   │   │       ├── number-field/
│   │   │       │   ├── NumberField.vue
│   │   │       │   ├── NumberFieldContent.vue
│   │   │       │   ├── NumberFieldDecrement.vue
│   │   │       │   ├── NumberFieldIncrement.vue
│   │   │       │   ├── NumberFieldInput.vue
│   │   │       │   └── index.ts
│   │   │       ├── select/
│   │   │       │   ├── Select.vue
│   │   │       │   ├── SelectContent.vue
│   │   │       │   ├── SelectGroup.vue
│   │   │       │   ├── SelectItem.vue
│   │   │       │   ├── SelectItemText.vue
│   │   │       │   ├── SelectLabel.vue
│   │   │       │   ├── SelectScrollDownButton.vue
│   │   │       │   ├── SelectScrollUpButton.vue
│   │   │       │   ├── SelectSeparator.vue
│   │   │       │   ├── SelectTrigger.vue
│   │   │       │   ├── SelectValue.vue
│   │   │       │   └── index.ts
│   │   │       ├── switch/
│   │   │       │   ├── Switch.vue
│   │   │       │   └── index.ts
│   │   │       ├── table/
│   │   │       │   ├── Table.vue
│   │   │       │   ├── TableBody.vue
│   │   │       │   ├── TableCaption.vue
│   │   │       │   ├── TableCell.vue
│   │   │       │   ├── TableEmpty.vue
│   │   │       │   ├── TableFooter.vue
│   │   │       │   ├── TableHead.vue
│   │   │       │   ├── TableHeader.vue
│   │   │       │   ├── TableRow.vue
│   │   │       │   └── index.ts
│   │   │       └── tabs/
│   │   │           ├── Tabs.vue
│   │   │           ├── TabsContent.vue
│   │   │           ├── TabsList.vue
│   │   │           ├── TabsTrigger.vue
│   │   │           └── index.ts
│   │   ├── Layouts/
│   │   │   └── AppLayout.vue
│   │   ├── Pages/
│   │   │   ├── API/
│   │   │   │   ├── Index.vue
│   │   │   │   └── Partials/
│   │   │   │       └── ApiTokenManager.vue
│   │   │   ├── Auth/
│   │   │   │   ├── ConfirmPassword.vue
│   │   │   │   ├── ForgotPassword.vue
│   │   │   │   ├── Login.vue
│   │   │   │   ├── Register.vue
│   │   │   │   ├── ResetPassword.vue
│   │   │   │   ├── TwoFactorChallenge.vue
│   │   │   │   └── VerifyEmail.vue
│   │   │   ├── Calendar.vue
│   │   │   ├── Clients.vue
│   │   │   ├── Dashboard.vue
│   │   │   ├── Import.vue
│   │   │   ├── Members.vue
│   │   │   ├── PrivacyPolicy.vue
│   │   │   ├── Profile/
│   │   │   │   ├── Partials/
│   │   │   │   │   ├── ApiTokensForm.vue
│   │   │   │   │   ├── DeleteUserForm.vue
│   │   │   │   │   ├── LogoutOtherBrowserSessionsForm.vue
│   │   │   │   │   ├── ThemeForm.vue
│   │   │   │   │   ├── TwoFactorAuthenticationForm.vue
│   │   │   │   │   ├── UpdatePasswordForm.vue
│   │   │   │   │   └── UpdateProfileInformationForm.vue
│   │   │   │   └── Show.vue
│   │   │   ├── ProjectShow.vue
│   │   │   ├── Projects.vue
│   │   │   ├── Reporting.vue
│   │   │   ├── ReportingDetailed.vue
│   │   │   ├── ReportingShared.vue
│   │   │   ├── SharedReport.vue
│   │   │   ├── Tags.vue
│   │   │   ├── Teams/
│   │   │   │   ├── Create.vue
│   │   │   │   ├── Partials/
│   │   │   │   │   ├── CreateTeamForm.vue
│   │   │   │   │   ├── DeleteTeamForm.vue
│   │   │   │   │   ├── ExportData.vue
│   │   │   │   │   ├── ImportData.vue
│   │   │   │   │   ├── OrganizationBillableRate.vue
│   │   │   │   │   ├── OrganizationFormatSettings.vue
│   │   │   │   │   ├── OrganizationTimeEntrySettings.vue
│   │   │   │   │   ├── TeamMemberManager.vue
│   │   │   │   │   └── UpdateTeamNameForm.vue
│   │   │   │   └── Show.vue
│   │   │   ├── TermsOfService.vue
│   │   │   ├── Time.vue
│   │   │   └── Welcome.vue
│   │   ├── app.ts
│   │   ├── bootstrap.js
│   │   ├── lib/
│   │   │   └── utils.ts
│   │   ├── packages/
│   │   │   ├── api/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── package.json
│   │   │   │   ├── src/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── openapi.json.client.ts
│   │   │   │   ├── tsconfig.json
│   │   │   │   └── vite.config.js
│   │   │   └── ui/
│   │   │       ├── .gitignore
│   │   │       ├── package.json
│   │   │       ├── src/
│   │   │       │   ├── Badge.vue
│   │   │       │   ├── BillableRateModal.vue
│   │   │       │   ├── Buttons/
│   │   │       │   │   ├── Button.vue
│   │   │       │   │   ├── DangerButton.vue
│   │   │       │   │   ├── PrimaryButton.vue
│   │   │       │   │   ├── SecondaryButton.vue
│   │   │       │   │   └── index.ts
│   │   │       │   ├── CardTitle.vue
│   │   │       │   ├── Client/
│   │   │       │   │   ├── ClientDropdown.vue
│   │   │       │   │   └── ClientDropdownItem.vue
│   │   │       │   ├── CommandPalette/
│   │   │       │   │   ├── CommandPalette.vue
│   │   │       │   │   ├── CommandPaletteTypes.ts
│   │   │       │   │   └── index.ts
│   │   │       │   ├── DialogModal.vue
│   │   │       │   ├── EstimatedTimeProgress.vue
│   │   │       │   ├── EstimatedTimeSection.vue
│   │   │       │   ├── FullCalendar/
│   │   │       │   │   ├── CalendarSettingsPopover.vue
│   │   │       │   │   ├── FullCalendarDayHeader.vue
│   │   │       │   │   ├── FullCalendarEventContent.vue
│   │   │       │   │   ├── TimeEntryCalendar.vue
│   │   │       │   │   ├── calendarSettings.ts
│   │   │       │   │   ├── idleStatusPlugin.ts
│   │   │       │   │   └── useVisualSnap.ts
│   │   │       │   ├── GroupedItemsCountButton.vue
│   │   │       │   ├── Icons/
│   │   │       │   │   ├── BillableIcon.vue
│   │   │       │   │   ├── DollarIcon.vue
│   │   │       │   │   ├── EuroIcon.vue
│   │   │       │   │   └── ListFilterIcon.vue
│   │   │       │   ├── Input/
│   │   │       │   │   ├── BillableRateInput.vue
│   │   │       │   │   ├── BillableToggleButton.vue
│   │   │       │   │   ├── Checkbox.vue
│   │   │       │   │   ├── DatePicker.vue
│   │   │       │   │   ├── DateRangePicker.vue
│   │   │       │   │   ├── Dropdown.vue
│   │   │       │   │   ├── DurationHumanInput.vue
│   │   │       │   │   ├── EstimatedTimeInput.vue
│   │   │       │   │   ├── InputError.vue
│   │   │       │   │   ├── InputLabel.vue
│   │   │       │   │   ├── MultiselectDropdown.vue
│   │   │       │   │   ├── TextInput.vue
│   │   │       │   │   ├── TextareaInput.vue
│   │   │       │   │   ├── TimePickerSimple.vue
│   │   │       │   │   └── TimeRangeSelector.vue
│   │   │       │   ├── LoadingSpinner.vue
│   │   │       │   ├── MainContainer.vue
│   │   │       │   ├── Modal.vue
│   │   │       │   ├── Project/
│   │   │       │   │   ├── ProjectBadge.vue
│   │   │       │   │   ├── ProjectBillableRateModal.vue
│   │   │       │   │   ├── ProjectBillableSelect.vue
│   │   │       │   │   ├── ProjectColorSelector.vue
│   │   │       │   │   ├── ProjectCreateModal.vue
│   │   │       │   │   ├── ProjectDropdownItem.vue
│   │   │       │   │   └── ProjectEditBillableSection.vue
│   │   │       │   ├── Tag/
│   │   │       │   │   ├── TagBadge.vue
│   │   │       │   │   ├── TagCreateModal.vue
│   │   │       │   │   └── TagDropdown.vue
│   │   │       │   ├── TimeEntry/
│   │   │       │   │   ├── TimeEntryAggregateRow.vue
│   │   │       │   │   ├── TimeEntryCreateModal.vue
│   │   │       │   │   ├── TimeEntryDescriptionInput.vue
│   │   │       │   │   ├── TimeEntryEditModal.vue
│   │   │       │   │   ├── TimeEntryGroupedTable.vue
│   │   │       │   │   ├── TimeEntryMassActionRow.vue
│   │   │       │   │   ├── TimeEntryMassUpdateModal.vue
│   │   │       │   │   ├── TimeEntryMoreOptionsDropdown.vue
│   │   │       │   │   ├── TimeEntryRangeSelector.vue
│   │   │       │   │   ├── TimeEntryRow.vue
│   │   │       │   │   ├── TimeEntryRowDurationInput.vue
│   │   │       │   │   ├── TimeEntryRowHeading.vue
│   │   │       │   │   └── TimeEntryRowTagDropdown.vue
│   │   │       │   ├── TimeTracker/
│   │   │       │   │   ├── TimeTrackerControls.vue
│   │   │       │   │   ├── TimeTrackerMoreOptionsDropdown.vue
│   │   │       │   │   ├── TimeTrackerProjectTaskDropdown.vue
│   │   │       │   │   ├── TimeTrackerRangeSelector.vue
│   │   │       │   │   ├── TimeTrackerRecentlyTrackedEntry.vue
│   │   │       │   │   ├── TimeTrackerRunningInDifferentOrganizationOverlay.vue
│   │   │       │   │   └── TimeTrackerTagDropdown.vue
│   │   │       │   ├── TimeTrackerStartStop.vue
│   │   │       │   ├── TimezoneMismatchModal.vue
│   │   │       │   ├── accordion/
│   │   │       │   │   ├── Accordion.vue
│   │   │       │   │   ├── AccordionContent.vue
│   │   │       │   │   ├── AccordionItem.vue
│   │   │       │   │   ├── AccordionTrigger.vue
│   │   │       │   │   └── index.ts
│   │   │       │   ├── command/
│   │   │       │   │   ├── Command.vue
│   │   │       │   │   ├── CommandGroup.vue
│   │   │       │   │   ├── CommandInput.vue
│   │   │       │   │   ├── CommandItem.vue
│   │   │       │   │   ├── CommandList.vue
│   │   │       │   │   ├── CommandSeparator.vue
│   │   │       │   │   ├── CommandShortcut.vue
│   │   │       │   │   └── index.ts
│   │   │       │   ├── field/
│   │   │       │   │   ├── Field.vue
│   │   │       │   │   ├── FieldContent.vue
│   │   │       │   │   ├── FieldDescription.vue
│   │   │       │   │   ├── FieldError.vue
│   │   │       │   │   ├── FieldGroup.vue
│   │   │       │   │   ├── FieldLabel.vue
│   │   │       │   │   ├── FieldLegend.vue
│   │   │       │   │   ├── FieldSeparator.vue
│   │   │       │   │   ├── FieldSet.vue
│   │   │       │   │   ├── FieldTitle.vue
│   │   │       │   │   └── index.ts
│   │   │       │   ├── index.ts
│   │   │       │   ├── popover/
│   │   │       │   │   ├── Popover.vue
│   │   │       │   │   ├── PopoverContent.vue
│   │   │       │   │   ├── PopoverTrigger.vue
│   │   │       │   │   └── index.ts
│   │   │       │   ├── range-calendar/
│   │   │       │   │   ├── RangeCalendar.vue
│   │   │       │   │   ├── RangeCalendarCell.vue
│   │   │       │   │   ├── RangeCalendarCellTrigger.vue
│   │   │       │   │   ├── RangeCalendarGrid.vue
│   │   │       │   │   ├── RangeCalendarGridBody.vue
│   │   │       │   │   ├── RangeCalendarGridHead.vue
│   │   │       │   │   ├── RangeCalendarGridRow.vue
│   │   │       │   │   ├── RangeCalendarHeadCell.vue
│   │   │       │   │   ├── RangeCalendarHeader.vue
│   │   │       │   │   ├── RangeCalendarHeading.vue
│   │   │       │   │   ├── RangeCalendarNextButton.vue
│   │   │       │   │   ├── RangeCalendarPrevButton.vue
│   │   │       │   │   └── index.ts
│   │   │       │   ├── separator/
│   │   │       │   │   ├── Separator.vue
│   │   │       │   │   └── index.ts
│   │   │       │   ├── tooltip/
│   │   │       │   │   ├── Tooltip.vue
│   │   │       │   │   ├── TooltipContent.vue
│   │   │       │   │   ├── TooltipProvider.vue
│   │   │       │   │   ├── TooltipTrigger.vue
│   │   │       │   │   └── index.ts
│   │   │       │   └── utils/
│   │   │       │       ├── cn.ts
│   │   │       │       ├── color.ts
│   │   │       │       ├── money.ts
│   │   │       │       ├── number.ts
│   │   │       │       ├── random.ts
│   │   │       │       ├── select.ts
│   │   │       │       ├── settings.ts
│   │   │       │       └── time.ts
│   │   │       ├── styles.css
│   │   │       ├── tailwind.theme.js
│   │   │       ├── tsconfig.json
│   │   │       └── vite.config.js
│   │   ├── types/
│   │   │   ├── dom.d.ts
│   │   │   ├── dom.ts
│   │   │   ├── global.d.ts
│   │   │   ├── inertia.d.ts
│   │   │   ├── jetstream.ts
│   │   │   ├── models.d.ts
│   │   │   ├── models.ts
│   │   │   ├── projects.d.ts
│   │   │   ├── reporting.ts
│   │   │   ├── time-entries.d.ts
│   │   │   ├── vite-env.d.ts
│   │   │   └── vue-shim.d.ts
│   │   ├── utils/
│   │   │   ├── billing.ts
│   │   │   ├── commandPaletteCommands.ts
│   │   │   ├── feedback.ts
│   │   │   ├── fetchAllPages.ts
│   │   │   ├── format.ts
│   │   │   ├── init.ts
│   │   │   ├── money.ts
│   │   │   ├── notification.ts
│   │   │   ├── permissions.ts
│   │   │   ├── prefetch.ts
│   │   │   ├── roles.ts
│   │   │   ├── session.ts
│   │   │   ├── theme.ts
│   │   │   ├── useAggregatedTimeEntriesQuery.ts
│   │   │   ├── useClients.ts
│   │   │   ├── useClientsQuery.ts
│   │   │   ├── useCommandPalette.ts
│   │   │   ├── useCssVariable.ts
│   │   │   ├── useCurrentTimeEntry.ts
│   │   │   ├── useInvitations.ts
│   │   │   ├── useMembers.ts
│   │   │   ├── useMembersQuery.ts
│   │   │   ├── useOrganization.ts
│   │   │   ├── useOrganizationQuery.ts
│   │   │   ├── useProjectMembers.ts
│   │   │   ├── useProjectMembersQuery.ts
│   │   │   ├── useProjects.ts
│   │   │   ├── useProjectsQuery.ts
│   │   │   ├── useReporting.ts
│   │   │   ├── useReportsQuery.ts
│   │   │   ├── useTags.ts
│   │   │   ├── useTagsQuery.ts
│   │   │   ├── useTasks.ts
│   │   │   ├── useTasksQuery.ts
│   │   │   ├── useTimeEntriesCalendarQuery.ts
│   │   │   ├── useTimeEntriesInfiniteQuery.ts
│   │   │   ├── useTimeEntriesMutations.ts
│   │   │   ├── useTimeEntriesReportQuery.ts
│   │   │   └── useUser.ts
│   │   ├── ziggy.d.ts
│   │   └── ziggy.js
│   ├── markdown/
│   │   ├── policy.md
│   │   └── terms.md
│   ├── testfiles/
│   │   ├── clockify_projects_import_test_1.csv
│   │   ├── clockify_time_entries_import_test_1.csv
│   │   ├── clockify_time_entries_import_test_2.csv
│   │   ├── clockify_time_entries_import_test_3.csv
│   │   ├── generic_projects_import_test_1.csv
│   │   ├── generic_time_entries_import_test_1.csv
│   │   ├── harvest_clients_import_test_1.csv
│   │   ├── harvest_projects_import_test_1.csv
│   │   ├── harvest_time_entries_import_test_1.csv
│   │   ├── solidtime_import_test_1/
│   │   │   ├── clients.csv
│   │   │   ├── members.csv
│   │   │   ├── meta.json
│   │   │   ├── organization_invitations.csv
│   │   │   ├── organizations.csv
│   │   │   ├── project_members.csv
│   │   │   ├── projects.csv
│   │   │   ├── tags.csv
│   │   │   ├── tasks.csv
│   │   │   └── time_entries.csv
│   │   ├── toggl_data_import_test_1/
│   │   │   ├── clients.json
│   │   │   ├── projects.json
│   │   │   ├── projects_users/
│   │   │   │   ├── 401.json
│   │   │   │   ├── 402.json
│   │   │   │   └── 403.json
│   │   │   ├── tags.json
│   │   │   ├── tasks/
│   │   │   │   ├── 401.json
│   │   │   │   ├── 402.json
│   │   │   │   └── 403.json
│   │   │   └── workspace_users.json
│   │   ├── toggl_data_import_test_2/
│   │   │   ├── clients.json
│   │   │   ├── projects.json
│   │   │   ├── projects_users/
│   │   │   │   ├── 401.json
│   │   │   │   ├── 402.json
│   │   │   │   └── 403.json
│   │   │   ├── tags.json
│   │   │   ├── tasks/
│   │   │   │   ├── 401.json
│   │   │   │   ├── 402.json
│   │   │   │   └── 403.json
│   │   │   └── workspace_users.json
│   │   ├── toggl_time_entries_import_test_1.csv
│   │   └── toggl_time_entries_import_test_2.csv
│   └── views/
│       ├── app.blade.php
│       ├── auth/
│       │   └── oauth/
│       │       └── authorize.blade.php
│       ├── emails/
│       │   ├── auth-api-expiration-reminder.blade.php
│       │   ├── auth-api-token-expired.blade.php
│       │   ├── organization-invitation.blade.php
│       │   └── time-entry-still-running.blade.php
│       ├── filament/
│       │   └── widgets/
│       │       └── server-overview.blade.php
│       ├── reports/
│       │   ├── time-entry-aggregate/
│       │   │   ├── pdf-footer.blade.php
│       │   │   ├── pdf.blade.php
│       │   │   └── spreadsheet.blade.php
│       │   └── time-entry-index/
│       │       ├── pdf-footer.blade.php
│       │       └── pdf.blade.php
│       └── vendor/
│           └── mail/
│               ├── html/
│               │   ├── button.blade.php
│               │   ├── footer.blade.php
│               │   ├── header.blade.php
│               │   ├── layout.blade.php
│               │   ├── message.blade.php
│               │   ├── panel.blade.php
│               │   ├── subcopy.blade.php
│               │   ├── table.blade.php
│               │   └── themes/
│               │       └── default.css
│               └── text/
│                   ├── button.blade.php
│                   ├── footer.blade.php
│                   ├── header.blade.php
│                   ├── layout.blade.php
│                   ├── message.blade.php
│                   ├── panel.blade.php
│                   ├── subcopy.blade.php
│                   └── table.blade.php
├── routes/
│   ├── api.php
│   └── web.php
├── storage/
│   ├── app/
│   │   └── .gitignore
│   ├── framework/
│   │   ├── .gitignore
│   │   ├── cache/
│   │   │   └── .gitignore
│   │   ├── sessions/
│   │   │   └── .gitignore
│   │   ├── testing/
│   │   │   └── .gitignore
│   │   └── views/
│   │       └── .gitignore
│   └── logs/
│       └── .gitignore
├── tailwind.config.js
├── tests/
│   ├── CreatesApplication.php
│   ├── Feature/
│   │   ├── AuthenticationTest.php
│   │   ├── BrowserSessionsTest.php
│   │   ├── CreateOrganizationTest.php
│   │   ├── DeleteAccountTest.php
│   │   ├── DeleteOrganizationTest.php
│   │   ├── EmailVerificationTest.php
│   │   ├── InviteTeamMemberTest.php
│   │   ├── LeaveTeamTest.php
│   │   ├── PasswordConfirmationTest.php
│   │   ├── PasswordResetTest.php
│   │   ├── ProfileInformationTest.php
│   │   ├── RegistrationTest.php
│   │   ├── RemoveTeamMemberTest.php
│   │   ├── TwoFactorAuthenticationSettingsTest.php
│   │   ├── UpdatePasswordTest.php
│   │   ├── UpdateTeamMemberRoleTest.php
│   │   └── UpdateTeamTest.php
│   ├── TestCase.php
│   ├── TestCaseWithDatabase.php
│   └── Unit/
│       ├── Console/
│       │   ├── Commands/
│       │   │   ├── Admin/
│       │   │   │   ├── OrganizationDeleteCommandTest.php
│       │   │   │   ├── UserCreateCommandCommandTest.php
│       │   │   │   └── UserVerifyCommandTest.php
│       │   │   ├── Auth/
│       │   │   │   └── AuthSendReminderForExpiringApiTokensCommandTest.php
│       │   │   ├── Correction/
│       │   │   │   └── CorrectionPlaceholderMembersCommandTest.php
│       │   │   ├── Report/
│       │   │   │   └── ReportSetExpiredToPrivateCommandTest.php
│       │   │   ├── SelfHost/
│       │   │   │   ├── SelfHostCheckForUpdateCommandTest.php
│       │   │   │   ├── SelfHostDatabaseConsistencyCommandTest.php
│       │   │   │   ├── SelfHostGenerateKeysCommandTest.php
│       │   │   │   └── SelfHostTelemetryCommandTest.php
│       │   │   └── TimeEntry/
│       │   │       └── TimeEntrySendStillRunningMailsCommandTest.php
│       │   └── KernelTest.php
│       ├── Database/
│       │   ├── MigrationTest.php
│       │   └── SeederTest.php
│       ├── Endpoint/
│       │   ├── Api/
│       │   │   └── V1/
│       │   │       ├── ApiEndpointTestAbstract.php
│       │   │       ├── ApiTokenEndpointTest.php
│       │   │       ├── ChartEndpointTest.php
│       │   │       ├── ClientEndpointTest.php
│       │   │       ├── CurrencyEndpointTest.php
│       │   │       ├── ExportEndpointTest.php
│       │   │       ├── ImportEndpointTest.php
│       │   │       ├── InvitationEndpointTest.php
│       │   │       ├── MemberEndpointTest.php
│       │   │       ├── OrganizationEndpointTest.php
│       │   │       ├── ProjectEndpointTest.php
│       │   │       ├── ProjectMemberEndpointTest.php
│       │   │       ├── Public/
│       │   │       │   └── PublicReportEndpointTest.php
│       │   │       ├── ReportEndpointTest.php
│       │   │       ├── TagEndpointTest.php
│       │   │       ├── TaskEndpointTest.php
│       │   │       ├── TimeEntryEndpointTest.php
│       │   │       ├── UserEndpointTest.php
│       │   │       ├── UserMembershipEndpointTest.php
│       │   │       └── UserTimeEntryEndpointTest.php
│       │   └── Web/
│       │       ├── DashboardEndpointTest.php
│       │       ├── EndpointTestAbstract.php
│       │       ├── HealthCheckEndpointTest.php
│       │       └── HomeEndpointTest.php
│       ├── Filament/
│       │   ├── FilamentTestCase.php
│       │   ├── Resources/
│       │   │   ├── AuditResourceTest.php
│       │   │   ├── ClientResourceTest.php
│       │   │   ├── FailedJobResourceTest.php
│       │   │   ├── OrganizationInvitationResourceTest.php
│       │   │   ├── OrganizationResourceTest.php
│       │   │   ├── ProjectResourceTest.php
│       │   │   ├── ReportResourceTest.php
│       │   │   ├── TagResourceTest.php
│       │   │   ├── TaskResourceTest.php
│       │   │   ├── TimeEntryResourceTest.php
│       │   │   ├── TokenResourceTest.php
│       │   │   └── UserResourceTest.php
│       │   └── Widgets/
│       │       └── ServerOverviewWidgetTest.php
│       ├── Jobs/
│       │   ├── RecalculateSpentTimeForProjectTest.php
│       │   ├── RecalculateSpentTimeForTaskTest.php
│       │   └── Test/
│       │       └── TestJobTest.php
│       ├── Mail/
│       │   ├── AuthApiTokenExpirationReminderMailTest.php
│       │   ├── AuthApiTokenExpiredMailTest.php
│       │   ├── OrganizationInvitationMailTest.php
│       │   └── TimeEntryStillRunningMailTest.php
│       ├── Middleware/
│       │   ├── CheckOrganizationBlockedMiddlewareTest.php
│       │   ├── EnsureEmailIsVerifiedMiddlewareTest.php
│       │   ├── ForceHttpsMiddlewareTest.php
│       │   ├── HandleInertiaRequestsMiddlewareTest.php
│       │   └── MiddlewareTestAbstract.php
│       ├── Model/
│       │   ├── ClientModelTest.php
│       │   ├── MemberModelTest.php
│       │   ├── ModelTestAbstract.php
│       │   ├── OrganizationModelTest.php
│       │   ├── Passport/
│       │   │   └── TokenModelTest.php
│       │   ├── ProjectMemberModelTest.php
│       │   ├── ProjectModelTest.php
│       │   ├── ReportModelTest.php
│       │   ├── TagModelTest.php
│       │   ├── TaskModelTest.php
│       │   ├── TimeEntryModelTest.php
│       │   └── UserModelTest.php
│       ├── Rules/
│       │   ├── ColorRuleTest.php
│       │   └── CurrencyRuleTest.php
│       └── Service/
│           ├── BillableRateServiceTest.php
│           ├── CurrencyServiceTest.php
│           ├── DashboardServiceTest.php
│           ├── DeletionServiceTest.php
│           ├── Export/
│           │   └── ExportServiceTest.php
│           ├── Import/
│           │   ├── ImportDatabaseHelperTest.php
│           │   ├── ImportServiceTest.php
│           │   └── Importers/
│           │       ├── ClockifyProjectsImporterTest.php
│           │       ├── ClockifyTimeEntriesImporterTest.php
│           │       ├── GenericProjectsImporterTest.php
│           │       ├── GenericTimeEntriesImporterTest.php
│           │       ├── HarvestClientsImporterTest.php
│           │       ├── HarvestProjectsImporterTest.php
│           │       ├── HarvestTimeEntriesImporterTest.php
│           │       ├── ImporterProviderTest.php
│           │       ├── ImporterTestAbstract.php
│           │       ├── SolidtimeImporterTest.php
│           │       ├── TogglDataImporterTest.php
│           │       └── TogglTimeEntriesImporterTest.php
│           ├── IntervalServiceTest.php
│           ├── LocalizationServiceTest.php
│           ├── MemberServiceTest.php
│           ├── PermissionStoreTest.php
│           ├── TimeEntryAggregationServiceTest.php
│           ├── TimeEntryFilterTest.php
│           ├── TimezoneServiceTest.php
│           └── UserServiceTest.php
├── tsconfig.json
├── vite-module-loader.js
└── vite.config.js
Download .txt
Showing preview only (336K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2769 symbols across 622 files)

FILE: app/Actions/Fortify/CreateNewUser.php
  class CreateNewUser (line 22) | class CreateNewUser implements CreatesNewUsers
    method create (line 33) | public function create(array $input): User

FILE: app/Actions/Fortify/PasswordValidationRules.php
  type PasswordValidationRules (line 10) | trait PasswordValidationRules
    method passwordRules (line 17) | protected function passwordRules(): array

FILE: app/Actions/Fortify/ResetUserPassword.php
  class ResetUserPassword (line 12) | class ResetUserPassword implements ResetsUserPasswords
    method reset (line 21) | public function reset(User $user, array $input): void

FILE: app/Actions/Fortify/UpdateUserPassword.php
  class UpdateUserPassword (line 12) | class UpdateUserPassword implements UpdatesUserPasswords
    method update (line 21) | public function update(User $user, array $input): void

FILE: app/Actions/Fortify/UpdateUserProfileInformation.php
  class UpdateUserProfileInformation (line 16) | class UpdateUserProfileInformation implements UpdatesUserProfileInformation
    method update (line 25) | public function update(User $user, array $input): void

FILE: app/Actions/Jetstream/AddOrganizationMember.php
  class AddOrganizationMember (line 21) | class AddOrganizationMember implements AddsTeamMembers
    method add (line 26) | public function add(User $owner, Organization $organization, string $e...
    method validate (line 43) | protected function validate(Organization $organization, string $email,...
    method rules (line 58) | protected function rules(): array
    method ensureUserIsNotAlreadyOnTeam (line 84) | protected function ensureUserIsNotAlreadyOnTeam(Organization $team, st...

FILE: app/Actions/Jetstream/CreateOrganization.php
  class CreateOrganization (line 19) | class CreateOrganization implements CreatesTeams
    method create (line 29) | public function create(User $user, array $input): Organization

FILE: app/Actions/Jetstream/DeleteOrganization.php
  class DeleteOrganization (line 11) | class DeleteOrganization implements DeletesTeams
    method delete (line 16) | public function delete(Organization $organization): void

FILE: app/Actions/Jetstream/DeleteUser.php
  class DeleteUser (line 13) | class DeleteUser implements DeletesUsers
    method delete (line 20) | public function delete(User $user): void

FILE: app/Actions/Jetstream/InviteOrganizationMember.php
  class InviteOrganizationMember (line 13) | class InviteOrganizationMember implements InvitesTeamMembers
    method invite (line 20) | public function invite(User $user, Organization $organization, string ...

FILE: app/Actions/Jetstream/RemoveOrganizationMember.php
  class RemoveOrganizationMember (line 13) | class RemoveOrganizationMember implements RemovesTeamMembers
    method remove (line 20) | public function remove(User $user, Organization $organization, User $t...

FILE: app/Actions/Jetstream/UpdateMemberRole.php
  class UpdateMemberRole (line 14) | class UpdateMemberRole
    method update (line 21) | public function update(User $actingUser, Organization $organization, s...

FILE: app/Actions/Jetstream/UpdateOrganization.php
  class UpdateOrganization (line 16) | class UpdateOrganization implements UpdatesTeamNames
    method update (line 26) | public function update(User $user, Organization $organization, array $...

FILE: app/Actions/Jetstream/ValidateOrganizationDeletion.php
  class ValidateOrganizationDeletion (line 12) | class ValidateOrganizationDeletion
    method validate (line 22) | public function validate(User $user, Organization $organization): void

FILE: app/Console/Commands/Admin/OrganizationDeleteCommand.php
  class OrganizationDeleteCommand (line 12) | class OrganizationDeleteCommand extends Command
    method handle (line 32) | public function handle(DeletionService $deletionService): int

FILE: app/Console/Commands/Admin/UserCreateCommand.php
  class UserCreateCommand (line 15) | class UserCreateCommand extends Command
    method handle (line 38) | public function handle(): int

FILE: app/Console/Commands/Admin/UserVerifyCommand.php
  class UserVerifyCommand (line 11) | class UserVerifyCommand extends Command
    method handle (line 31) | public function handle(): int

FILE: app/Console/Commands/Auth/AuthSendReminderForExpiringApiTokensCommand.php
  class AuthSendReminderForExpiringApiTokensCommand (line 17) | class AuthSendReminderForExpiringApiTokensCommand extends Command
    method handle (line 37) | public function handle(): int

FILE: app/Console/Commands/Correction/CorrectionPlaceholderMembersCommand.php
  class CorrectionPlaceholderMembersCommand (line 13) | class CorrectionPlaceholderMembersCommand extends Command
    method handle (line 33) | public function handle(): int

FILE: app/Console/Commands/Report/ReportSetExpiredToPrivateCommand.php
  class ReportSetExpiredToPrivateCommand (line 13) | class ReportSetExpiredToPrivateCommand extends Command
    method handle (line 33) | public function handle(): int

FILE: app/Console/Commands/SelfHost/SelfHostCheckForUpdateCommand.php
  class SelfHostCheckForUpdateCommand (line 11) | class SelfHostCheckForUpdateCommand extends Command
    method handle (line 30) | public function handle(): int

FILE: app/Console/Commands/SelfHost/SelfHostDatabaseConsistency.php
  class SelfHostDatabaseConsistency (line 14) | class SelfHostDatabaseConsistency extends Command
    method handle (line 33) | public function handle(): int
    method logProblems (line 106) | private function logProblems(Collection $problems, string $message, bo...

FILE: app/Console/Commands/SelfHost/SelfHostGenerateKeysCommand.php
  class SelfHostGenerateKeysCommand (line 12) | class SelfHostGenerateKeysCommand extends Command
    method handle (line 34) | public function handle(): int

FILE: app/Console/Commands/SelfHost/SelfHostTelemetryCommand.php
  class SelfHostTelemetryCommand (line 10) | class SelfHostTelemetryCommand extends Command
    method handle (line 29) | public function handle(): int

FILE: app/Console/Commands/Test/TestEmailCommand.php
  class TestEmailCommand (line 11) | class TestEmailCommand extends Command
    method handle (line 30) | public function handle(): int

FILE: app/Console/Commands/Test/TestJobCommand.php
  class TestJobCommand (line 11) | class TestJobCommand extends Command
    method handle (line 30) | public function handle(): int

FILE: app/Console/Commands/Test/TestOutputCommand.php
  class TestOutputCommand (line 9) | class TestOutputCommand extends Command
    method handle (line 28) | public function handle(): int

FILE: app/Console/Commands/TimeEntry/TimeEntrySendStillRunningMailsCommand.php
  class TimeEntrySendStillRunningMailsCommand (line 16) | class TimeEntrySendStillRunningMailsCommand extends Command
    method handle (line 36) | public function handle(): int

FILE: app/Console/Kernel.php
  class Kernel (line 10) | class Kernel extends ConsoleKernel
    method schedule (line 15) | protected function schedule(Schedule $schedule): void
    method commands (line 55) | protected function commands(): void

FILE: app/Enums/CurrencyFormat.php
  method toSelectArray (line 27) | public static function toSelectArray(): array

FILE: app/Enums/DateFormat.php
  method toCarbonFormat (line 24) | public function toCarbonFormat(): string
  method toSelectArray (line 39) | public static function toSelectArray(): array

FILE: app/Enums/ExportFormat.php
  method getFileExtension (line 16) | public function getFileExtension(): string
  method getExportPackageType (line 26) | public function getExportPackageType(): string

FILE: app/Enums/IntervalFormat.php
  method toSelectArray (line 23) | public static function toSelectArray(): array

FILE: app/Enums/NumberFormat.php
  method toSelectArray (line 28) | public static function toSelectArray(): array

FILE: app/Enums/TimeEntryAggregationType.php
  method fromInterval (line 25) | public static function fromInterval(TimeEntryAggregationTypeInterval $ti...
  method toInterval (line 35) | public function toInterval(): ?TimeEntryAggregationTypeInterval

FILE: app/Enums/TimeFormat.php
  method toSelectArray (line 19) | public static function toSelectArray(): array

FILE: app/Enums/Weekday.php
  method toEndOfWeek (line 22) | public function toEndOfWeek(): self
  method carbonWeekDay (line 35) | public function carbonWeekDay(): int
  method toSelectArray (line 51) | public static function toSelectArray(): array

FILE: app/Events/AfterCreateOrganization.php
  class AfterCreateOrganization (line 15) | class AfterCreateOrganization
    method __construct (line 22) | public function __construct(Organization $organization)

FILE: app/Events/BeforeOrganizationDeletion.php
  class BeforeOrganizationDeletion (line 10) | class BeforeOrganizationDeletion
    method __construct (line 16) | public function __construct(Organization $organization)

FILE: app/Events/DatabaseSeederAfterSeed.php
  class DatabaseSeederAfterSeed (line 9) | class DatabaseSeederAfterSeed
    method __construct (line 13) | public function __construct() {}

FILE: app/Events/DatabaseSeederBeforeDelete.php
  class DatabaseSeederBeforeDelete (line 9) | class DatabaseSeederBeforeDelete
    method __construct (line 13) | public function __construct() {}

FILE: app/Events/MemberMadeToPlaceholder.php
  class MemberMadeToPlaceholder (line 11) | class MemberMadeToPlaceholder
    method __construct (line 19) | public function __construct(Member $member, Organization $organization)

FILE: app/Events/MemberRemoved.php
  class MemberRemoved (line 11) | class MemberRemoved
    method __construct (line 19) | public function __construct(Member $member, Organization $organization)

FILE: app/Events/NewsletterRegistered.php
  class NewsletterRegistered (line 9) | class NewsletterRegistered
    method __construct (line 22) | public function __construct(string $name, string $email, string $id)

FILE: app/Exceptions/Api/ApiException.php
  class ApiException (line 12) | abstract class ApiException extends Exception
    method __construct (line 16) | public function __construct()
    method render (line 24) | public function render(Request $request): JsonResponse
    method getKey (line 37) | public function getKey(): string
    method getTranslatedMessage (line 51) | public function getTranslatedMessage(): string
    method report (line 61) | public function report(): bool

FILE: app/Exceptions/Api/CanNotDeleteUserWhoIsOwnerOfOrganizationWithMultipleMembers.php
  class CanNotDeleteUserWhoIsOwnerOfOrganizationWithMultipleMembers (line 7) | class CanNotDeleteUserWhoIsOwnerOfOrganizationWithMultipleMembers extend...

FILE: app/Exceptions/Api/CanNotRemoveOwnerFromOrganization.php
  class CanNotRemoveOwnerFromOrganization (line 7) | class CanNotRemoveOwnerFromOrganization extends ApiException

FILE: app/Exceptions/Api/ChangingRoleOfPlaceholderIsNotAllowed.php
  class ChangingRoleOfPlaceholderIsNotAllowed (line 7) | class ChangingRoleOfPlaceholderIsNotAllowed extends ApiException

FILE: app/Exceptions/Api/ChangingRoleToPlaceholderIsNotAllowed.php
  class ChangingRoleToPlaceholderIsNotAllowed (line 7) | class ChangingRoleToPlaceholderIsNotAllowed extends ApiException

FILE: app/Exceptions/Api/EntityStillInUseApiException.php
  class EntityStillInUseApiException (line 7) | class EntityStillInUseApiException extends ApiException
    method __construct (line 13) | public function __construct(string $modelToDelete, string $modelInUse)
    method getTranslatedMessage (line 25) | #[\Override]

FILE: app/Exceptions/Api/FeatureIsNotAvailableInFreePlanApiException.php
  class FeatureIsNotAvailableInFreePlanApiException (line 7) | class FeatureIsNotAvailableInFreePlanApiException extends ApiException

FILE: app/Exceptions/Api/InactiveUserCanNotBeUsedApiException.php
  class InactiveUserCanNotBeUsedApiException (line 7) | class InactiveUserCanNotBeUsedApiException extends ApiException

FILE: app/Exceptions/Api/InvitationForTheEmailAlreadyExistsApiException.php
  class InvitationForTheEmailAlreadyExistsApiException (line 7) | class InvitationForTheEmailAlreadyExistsApiException extends ApiException

FILE: app/Exceptions/Api/OnlyOwnerCanChangeOwnership.php
  class OnlyOwnerCanChangeOwnership (line 7) | class OnlyOwnerCanChangeOwnership extends ApiException

FILE: app/Exceptions/Api/OnlyPlaceholdersCanBeMergedIntoAnotherMember.php
  class OnlyPlaceholdersCanBeMergedIntoAnotherMember (line 7) | class OnlyPlaceholdersCanBeMergedIntoAnotherMember extends ApiException

FILE: app/Exceptions/Api/OrganizationHasNoSubscriptionButMultipleMembersException.php
  class OrganizationHasNoSubscriptionButMultipleMembersException (line 7) | class OrganizationHasNoSubscriptionButMultipleMembersException extends A...

FILE: app/Exceptions/Api/OrganizationNeedsAtLeastOneOwner.php
  class OrganizationNeedsAtLeastOneOwner (line 7) | class OrganizationNeedsAtLeastOneOwner extends ApiException

FILE: app/Exceptions/Api/OverlappingTimeEntryApiException.php
  class OverlappingTimeEntryApiException (line 7) | class OverlappingTimeEntryApiException extends ApiException

FILE: app/Exceptions/Api/PdfRendererIsNotConfiguredException.php
  class PdfRendererIsNotConfiguredException (line 7) | class PdfRendererIsNotConfiguredException extends ApiException

FILE: app/Exceptions/Api/PersonalAccessClientIsNotConfiguredException.php
  class PersonalAccessClientIsNotConfiguredException (line 7) | class PersonalAccessClientIsNotConfiguredException extends ApiException

FILE: app/Exceptions/Api/ThisPlaceholderCanNotBeInvitedUseTheMergeToolInsteadException.php
  class ThisPlaceholderCanNotBeInvitedUseTheMergeToolInsteadException (line 7) | class ThisPlaceholderCanNotBeInvitedUseTheMergeToolInsteadException exte...

FILE: app/Exceptions/Api/TimeEntryCanNotBeRestartedApiException.php
  class TimeEntryCanNotBeRestartedApiException (line 7) | class TimeEntryCanNotBeRestartedApiException extends ApiException

FILE: app/Exceptions/Api/TimeEntryStillRunningApiException.php
  class TimeEntryStillRunningApiException (line 7) | class TimeEntryStillRunningApiException extends ApiException

FILE: app/Exceptions/Api/UserIsAlreadyMemberOfOrganizationApiException.php
  class UserIsAlreadyMemberOfOrganizationApiException (line 7) | class UserIsAlreadyMemberOfOrganizationApiException extends ApiException

FILE: app/Exceptions/Api/UserIsAlreadyMemberOfProjectApiException.php
  class UserIsAlreadyMemberOfProjectApiException (line 7) | class UserIsAlreadyMemberOfProjectApiException extends ApiException

FILE: app/Exceptions/Api/UserNotPlaceholderApiException.php
  class UserNotPlaceholderApiException (line 7) | class UserNotPlaceholderApiException extends ApiException

FILE: app/Exceptions/Handler.php
  class Handler (line 12) | class Handler extends ExceptionHandler
    method register (line 28) | public function register(): void
    method render (line 35) | public function render($request, Throwable $e): Response|RedirectResponse

FILE: app/Exceptions/MovedToApiException.php
  class MovedToApiException (line 9) | class MovedToApiException extends HttpException
    method __construct (line 11) | public function __construct()

FILE: app/Extensions/Auditing/Resolvers/CustomIpAddressResolver.php
  class CustomIpAddressResolver (line 11) | class CustomIpAddressResolver implements Resolver
    method anonymizeIpAddress (line 13) | private static function anonymizeIpAddress(string $ipAddress): string
    method resolve (line 23) | public static function resolve(Auditable $auditable): string

FILE: app/Extensions/Fortify/CustomLoginResponse.php
  class CustomLoginResponse (line 12) | class CustomLoginResponse extends LoginResponse
    method toResponse (line 19) | public function toResponse($request): Response

FILE: app/Extensions/Fortify/CustomTwoFactorLoginResponse.php
  class CustomTwoFactorLoginResponse (line 13) | class CustomTwoFactorLoginResponse implements TwoFactorLoginResponseCont...
    method toResponse (line 20) | public function toResponse($request): Response

FILE: app/Extensions/Scramble/ApiExceptionTypeToSchema.php
  class ApiExceptionTypeToSchema (line 17) | class ApiExceptionTypeToSchema extends ExceptionToResponseExtension
    method shouldHandle (line 19) | public function shouldHandle(Type $type): bool
    method toResponse (line 25) | public function toResponse(Type $type): Response
    method reference (line 53) | public function reference(ObjectType $type): Reference

FILE: app/Extensions/Scramble/PaginatedResourceCollectionTypeToSchema.php
  class PaginatedResourceCollectionTypeToSchema (line 23) | class PaginatedResourceCollectionTypeToSchema extends TypeToSchemaExtension
    method shouldHandle (line 25) | public function shouldHandle(Type $type): bool
    method toSchema (line 31) | public function toSchema(Type $type): ?OpenApiObjectType
    method toResponse (line 94) | public function toResponse(Type $type): ?Response

FILE: app/Filament/Resources/AuditResource.php
  class AuditResource (line 18) | class AuditResource extends Resource
    method form (line 26) | public static function form(Form $form): Form
    method table (line 52) | public static function table(Table $table): Table
    method getRelations (line 81) | public static function getRelations(): array
    method getPages (line 87) | public static function getPages(): array

FILE: app/Filament/Resources/AuditResource/Pages/CreateAudit.php
  class CreateAudit (line 10) | class CreateAudit extends CreateRecord

FILE: app/Filament/Resources/AuditResource/Pages/ListAudits.php
  class ListAudits (line 10) | class ListAudits extends ListRecords
    method getHeaderActions (line 14) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/AuditResource/Pages/ViewAudit.php
  class ViewAudit (line 10) | class ViewAudit extends ViewRecord

FILE: app/Filament/Resources/ClientResource.php
  class ClientResource (line 17) | class ClientResource extends Resource
    method form (line 27) | public static function form(Form $form): Form
    method table (line 42) | public static function table(Table $table): Table
    method getRelations (line 81) | public static function getRelations(): array
    method getPages (line 88) | public static function getPages(): array

FILE: app/Filament/Resources/ClientResource/Pages/CreateClient.php
  class CreateClient (line 10) | class CreateClient extends CreateRecord

FILE: app/Filament/Resources/ClientResource/Pages/EditClient.php
  class EditClient (line 11) | class EditClient extends EditRecord
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/ClientResource/Pages/ListClients.php
  class ListClients (line 11) | class ListClients extends ListRecords
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/FailedJobResource.php
  class FailedJobResource (line 29) | class FailedJobResource extends Resource
    method getNavigationBadge (line 37) | public static function getNavigationBadge(): ?string
    method form (line 42) | public static function form(Form $form): Form
    method table (line 58) | public static function table(Table $table): Table
    method getPages (line 111) | public static function getPages(): array

FILE: app/Filament/Resources/FailedJobResource/Pages/ListFailedJobs.php
  class ListFailedJobs (line 14) | class ListFailedJobs extends ListRecords
    method getHeaderActions (line 18) | public function getHeaderActions(): array

FILE: app/Filament/Resources/FailedJobResource/Pages/ViewFailedJobs.php
  class ViewFailedJobs (line 10) | class ViewFailedJobs extends ViewRecord

FILE: app/Filament/Resources/OrganizationInvitationResource.php
  class OrganizationInvitationResource (line 19) | class OrganizationInvitationResource extends Resource
    method form (line 31) | public static function form(Form $form): Form
    method table (line 59) | public static function table(Table $table): Table
    method getRelations (line 100) | public static function getRelations(): array
    method getPages (line 106) | public static function getPages(): array

FILE: app/Filament/Resources/OrganizationInvitationResource/Pages/EditOrganizationInvitation.php
  class EditOrganizationInvitation (line 11) | class EditOrganizationInvitation extends EditRecord
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/OrganizationInvitationResource/Pages/ListOrganizationInvitations.php
  class ListOrganizationInvitations (line 10) | class ListOrganizationInvitations extends ListRecords
    method getHeaderActions (line 14) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/OrganizationInvitationResource/Pages/ViewOrganizationInvitation.php
  class ViewOrganizationInvitation (line 11) | class ViewOrganizationInvitation extends ViewRecord
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/OrganizationResource.php
  class OrganizationResource (line 35) | class OrganizationResource extends Resource
    method form (line 45) | public static function form(Form $form): Form
    method table (line 113) | public static function table(Table $table): Table
    method getRelations (line 237) | public static function getRelations(): array
    method getPages (line 245) | public static function getPages(): array

FILE: app/Filament/Resources/OrganizationResource/Actions/DeleteOrganization.php
  class DeleteOrganization (line 13) | class DeleteOrganization extends DeleteAction
    method setUp (line 15) | protected function setUp(): void

FILE: app/Filament/Resources/OrganizationResource/Pages/CreateOrganization.php
  class CreateOrganization (line 12) | class CreateOrganization extends CreateRecord
    method mutateFormDataBeforeCreate (line 16) | protected function mutateFormDataBeforeCreate(array $data): array
    method afterCreate (line 23) | protected function afterCreate(): void

FILE: app/Filament/Resources/OrganizationResource/Pages/EditOrganization.php
  class EditOrganization (line 10) | class EditOrganization extends EditRecord
    method getHeaderActions (line 14) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/OrganizationResource/Pages/ListOrganizations.php
  class ListOrganizations (line 11) | class ListOrganizations extends ListRecords
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/OrganizationResource/Pages/ViewOrganization.php
  class ViewOrganization (line 11) | class ViewOrganization extends ViewRecord
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/OrganizationResource/RelationManagers/InvitationsRelationManager.php
  class InvitationsRelationManager (line 22) | class InvitationsRelationManager extends RelationManager
    method form (line 28) | public function form(Form $form): Form
    method table (line 49) | public function table(Table $table): Table

FILE: app/Filament/Resources/OrganizationResource/RelationManagers/UsersRelationManager.php
  class UsersRelationManager (line 27) | class UsersRelationManager extends RelationManager
    method form (line 31) | public function form(Form $form): Form
    method table (line 44) | public function table(Table $table): Table

FILE: app/Filament/Resources/ProjectMemberResource.php
  class ProjectMemberResource (line 15) | class ProjectMemberResource extends Resource
    method form (line 21) | public static function form(Form $form): Form
    method table (line 44) | public static function table(Table $table): Table
    method getRelations (line 76) | public static function getRelations(): array
    method getPages (line 83) | public static function getPages(): array

FILE: app/Filament/Resources/ProjectMemberResource/Pages/CreateProjectMember.php
  class CreateProjectMember (line 10) | class CreateProjectMember extends CreateRecord

FILE: app/Filament/Resources/ProjectMemberResource/Pages/EditProjectMember.php
  class EditProjectMember (line 11) | class EditProjectMember extends EditRecord
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/ProjectMemberResource/Pages/ListProjectMembers.php
  class ListProjectMembers (line 11) | class ListProjectMembers extends ListRecords
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/ProjectMemberResource/Pages/ViewProjectMembers.php
  class ViewProjectMembers (line 11) | class ViewProjectMembers extends ViewRecord
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/ProjectResource.php
  class ProjectResource (line 20) | class ProjectResource extends Resource
    method form (line 30) | public static function form(Form $form): Form
    method table (line 58) | public static function table(Table $table): Table
    method getRelations (line 94) | public static function getRelations(): array
    method getPages (line 101) | public static function getPages(): array

FILE: app/Filament/Resources/ProjectResource/Pages/CreateProject.php
  class CreateProject (line 10) | class CreateProject extends CreateRecord

FILE: app/Filament/Resources/ProjectResource/Pages/EditProject.php
  class EditProject (line 11) | class EditProject extends EditRecord
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/ProjectResource/Pages/ListProjects.php
  class ListProjects (line 11) | class ListProjects extends ListRecords
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/ProjectResource/RelationManagers/ProjectMembersRelationManager.php
  class ProjectMembersRelationManager (line 15) | class ProjectMembersRelationManager extends RelationManager
    method form (line 21) | public function form(Form $form): Form
    method table (line 28) | public function table(Table $table): Table

FILE: app/Filament/Resources/ReportResource.php
  class ReportResource (line 23) | class ReportResource extends Resource
    method form (line 33) | public static function form(Form $form): Form
    method table (line 77) | public static function table(Table $table): Table
    method getRelations (line 127) | public static function getRelations(): array
    method getPages (line 133) | public static function getPages(): array

FILE: app/Filament/Resources/ReportResource/Pages/EditReport.php
  class EditReport (line 11) | class EditReport extends EditRecord
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/ReportResource/Pages/ListReports.php
  class ListReports (line 10) | class ListReports extends ListRecords
    method getHeaderActions (line 14) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/ReportResource/Pages/ViewReport.php
  class ViewReport (line 11) | class ViewReport extends ViewRecord
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/TagResource.php
  class TagResource (line 17) | class TagResource extends Resource
    method form (line 27) | public static function form(Form $form): Form
    method table (line 42) | public static function table(Table $table): Table
    method getRelations (line 81) | public static function getRelations(): array
    method getPages (line 88) | public static function getPages(): array

FILE: app/Filament/Resources/TagResource/Pages/CreateTag.php
  class CreateTag (line 10) | class CreateTag extends CreateRecord

FILE: app/Filament/Resources/TagResource/Pages/EditTag.php
  class EditTag (line 11) | class EditTag extends EditRecord
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/TagResource/Pages/ListTags.php
  class ListTags (line 11) | class ListTags extends ListRecords
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/TaskResource.php
  class TaskResource (line 17) | class TaskResource extends Resource
    method form (line 27) | public static function form(Form $form): Form
    method table (line 46) | public static function table(Table $table): Table
    method getRelations (line 83) | public static function getRelations(): array
    method getPages (line 90) | public static function getPages(): array

FILE: app/Filament/Resources/TaskResource/Pages/CreateTask.php
  class CreateTask (line 10) | class CreateTask extends CreateRecord

FILE: app/Filament/Resources/TaskResource/Pages/EditTask.php
  class EditTask (line 11) | class EditTask extends EditRecord
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/TaskResource/Pages/ListTasks.php
  class ListTasks (line 11) | class ListTasks extends ListRecords
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/TimeEntryResource.php
  class TimeEntryResource (line 22) | class TimeEntryResource extends Resource
    method form (line 32) | public static function form(Form $form): Form
    method table (line 76) | public static function table(Table $table): Table
    method getRelations (line 124) | public static function getRelations(): array
    method getPages (line 131) | public static function getPages(): array

FILE: app/Filament/Resources/TimeEntryResource/Pages/CreateTimeEntry.php
  class CreateTimeEntry (line 11) | class CreateTimeEntry extends CreateRecord
    method mutateFormDataBeforeCreate (line 19) | protected function mutateFormDataBeforeCreate(array $data): array

FILE: app/Filament/Resources/TimeEntryResource/Pages/EditTimeEntry.php
  class EditTimeEntry (line 12) | class EditTimeEntry extends EditRecord
    method getHeaderActions (line 16) | protected function getHeaderActions(): array
    method mutateFormDataBeforeSave (line 28) | protected function mutateFormDataBeforeSave(array $data): array

FILE: app/Filament/Resources/TimeEntryResource/Pages/ListTimeEntries.php
  class ListTimeEntries (line 11) | class ListTimeEntries extends ListRecords
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/TokenResource.php
  class TokenResource (line 17) | class TokenResource extends Resource
    method form (line 27) | public static function form(Form $form): Form
    method table (line 68) | public static function table(Table $table): Table
    method getRelations (line 130) | public static function getRelations(): array
    method getPages (line 136) | public static function getPages(): array

FILE: app/Filament/Resources/TokenResource/Pages/ListTokens.php
  class ListTokens (line 10) | class ListTokens extends ListRecords
    method getHeaderActions (line 14) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/TokenResource/Pages/ViewToken.php
  class ViewToken (line 10) | class ViewToken extends ViewRecord
    method getHeaderActions (line 14) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/UserResource.php
  class UserResource (line 32) | class UserResource extends Resource
    method form (line 42) | public static function form(Form $form): Form
    method table (line 130) | public static function table(Table $table): Table
    method getRelations (line 222) | public static function getRelations(): array
    method getPages (line 230) | public static function getPages(): array

FILE: app/Filament/Resources/UserResource/Actions/DeleteUser.php
  class DeleteUser (line 13) | class DeleteUser extends DeleteAction
    method setUp (line 15) | protected function setUp(): void

FILE: app/Filament/Resources/UserResource/Pages/CreateUser.php
  class CreateUser (line 13) | class CreateUser extends CreateRecord
    method handleRecordCreation (line 17) | protected function handleRecordCreation(array $data): User

FILE: app/Filament/Resources/UserResource/Pages/EditUser.php
  class EditUser (line 11) | class EditUser extends EditRecord
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/UserResource/Pages/ListUsers.php
  class ListUsers (line 11) | class ListUsers extends ListRecords
    method getHeaderActions (line 15) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/UserResource/Pages/ViewUser.php
  class ViewUser (line 12) | class ViewUser extends ViewRecord
    method getHeaderActions (line 16) | protected function getHeaderActions(): array

FILE: app/Filament/Resources/UserResource/RelationManagers/OrganizationsRelationManager.php
  class OrganizationsRelationManager (line 23) | class OrganizationsRelationManager extends RelationManager
    method form (line 27) | public function form(Form $form): Form
    method table (line 36) | public function table(Table $table): Table

FILE: app/Filament/Resources/UserResource/RelationManagers/OwnedOrganizationsRelationManager.php
  class OwnedOrganizationsRelationManager (line 15) | class OwnedOrganizationsRelationManager extends RelationManager
    method form (line 21) | public function form(Form $form): Form
    method table (line 28) | public function table(Table $table): Table

FILE: app/Filament/Widgets/ActiveUserOverview.php
  class ActiveUserOverview (line 13) | class ActiveUserOverview extends BaseWidget
    method getCards (line 19) | protected function getCards(): array

FILE: app/Filament/Widgets/ServerOverview.php
  class ServerOverview (line 10) | class ServerOverview extends Widget
    method getViewData (line 17) | protected function getViewData(): array

FILE: app/Filament/Widgets/TimeEntriesCreated.php
  class TimeEntriesCreated (line 12) | class TimeEntriesCreated extends ChartWidget
    method getData (line 20) | protected function getData(): array
    method getFilters (line 64) | protected function getFilters(): ?array
    method getType (line 73) | protected function getType(): string

FILE: app/Filament/Widgets/TimeEntriesImported.php
  class TimeEntriesImported (line 12) | class TimeEntriesImported extends ChartWidget
    method getData (line 20) | protected function getData(): array
    method getFilters (line 64) | protected function getFilters(): ?array
    method getType (line 73) | protected function getType(): string

FILE: app/Filament/Widgets/UserRegistrations.php
  class UserRegistrations (line 12) | class UserRegistrations extends ChartWidget
    method getData (line 20) | protected function getData(): array
    method getFilters (line 65) | protected function getFilters(): ?array
    method getType (line 74) | protected function getType(): string

FILE: app/Http/Controllers/Api/V1/ApiTokenController.php
  class ApiTokenController (line 18) | class ApiTokenController extends Controller
    method index (line 29) | public function index(): ApiTokenCollection
    method store (line 54) | public function store(ApiTokenStoreRequest $request): ApiTokenWithAcce...
    method revoke (line 83) | public function revoke(Token $apiToken): JsonResponse
    method destroy (line 106) | public function destroy(Token $apiToken): JsonResponse

FILE: app/Http/Controllers/Api/V1/ChartController.php
  class ChartController (line 14) | class ChartController extends Controller
    method weeklyProjectOverview (line 25) | public function weeklyProjectOverview(Organization $organization, Dash...
    method latestTasks (line 44) | public function latestTasks(Organization $organization, DashboardServi...
    method lastSevenDays (line 63) | public function lastSevenDays(Organization $organization, DashboardSer...
    method latestTeamActivity (line 82) | public function latestTeamActivity(Organization $organization, Dashboa...
    method dailyTrackedHours (line 100) | public function dailyTrackedHours(Organization $organization, Dashboar...
    method totalWeeklyTime (line 119) | public function totalWeeklyTime(Organization $organization, DashboardS...
    method totalWeeklyBillableTime (line 138) | public function totalWeeklyBillableTime(Organization $organization, Da...
    method totalWeeklyBillableAmount (line 157) | public function totalWeeklyBillableAmount(Organization $organization, ...
    method weeklyHistory (line 181) | public function weeklyHistory(Organization $organization, DashboardSer...

FILE: app/Http/Controllers/Api/V1/ClientController.php
  class ClientController (line 19) | class ClientController extends Controller
    method checkPermission (line 21) | protected function checkPermission(Organization $organization, string ...
    method index (line 38) | public function index(Organization $organization, ClientIndexRequest $...
    method store (line 71) | public function store(Organization $organization, ClientStoreRequest $...
    method update (line 90) | public function update(Organization $organization, Client $client, Cli...
    method destroy (line 110) | public function destroy(Organization $organization, Client $client): J...

FILE: app/Http/Controllers/Api/V1/Controller.php
  class Controller (line 12) | class Controller extends \App\Http\Controllers\Controller
    method __construct (line 14) | public function __construct(
    method checkPermission (line 21) | protected function checkPermission(Organization $organization, string ...
    method checkAnyPermission (line 33) | protected function checkAnyPermission(Organization $organization, arra...
    method hasPermission (line 43) | protected function hasPermission(Organization $organization, string $p...
    method canAccessPremiumFeatures (line 48) | protected function canAccessPremiumFeatures(Organization $organization...

FILE: app/Http/Controllers/Api/V1/CurrencyController.php
  class CurrencyController (line 13) | class CurrencyController extends Controller
    method index (line 22) | public function index(): JsonResponse

FILE: app/Http/Controllers/Api/V1/ExportController.php
  class ExportController (line 15) | class ExportController extends Controller
    method export (line 25) | public function export(Organization $organization, ExportService $expo...

FILE: app/Http/Controllers/Api/V1/ImportController.php
  class ImportController (line 16) | class ImportController extends Controller
    method index (line 27) | public function index(Organization $organization, ImporterProvider $im...
    method import (line 58) | public function import(Organization $organization, ImportRequest $requ...

FILE: app/Http/Controllers/Api/V1/InvitationController.php
  class InvitationController (line 20) | class InvitationController extends Controller
    method checkPermission (line 22) | protected function checkPermission(Organization $organization, string ...
    method index (line 39) | public function index(Organization $organization, InvitationIndexReque...
    method store (line 59) | public function store(Organization $organization, InvitationStoreReque...
    method resend (line 78) | public function resend(Organization $organization, OrganizationInvitat...
    method destroy (line 94) | public function destroy(Organization $organization, OrganizationInvita...

FILE: app/Http/Controllers/Api/V1/MemberController.php
  class MemberController (line 37) | class MemberController extends Controller
    method checkPermission (line 39) | protected function checkPermission(Organization $organization, string ...
    method index (line 56) | public function index(Organization $organization, MemberIndexRequest $...
    method update (line 80) | public function update(Organization $organization, Member $member, Mem...
    method destroy (line 106) | public function destroy(MemberDestroyRequest $request, Organization $o...
    method makePlaceholder (line 125) | public function makePlaceholder(Organization $organization, Member $me...
    method mergeInto (line 152) | public function mergeInto(Organization $organization, Member $member, ...
    method invitePlaceholder (line 182) | public function invitePlaceholder(Organization $organization, Member $...

FILE: app/Http/Controllers/Api/V1/OrganizationController.php
  class OrganizationController (line 14) | class OrganizationController extends Controller
    method show (line 23) | public function show(Organization $organization): OrganizationResource
    method update (line 39) | public function update(Organization $organization, OrganizationUpdateR...

FILE: app/Http/Controllers/Api/V1/ProjectController.php
  class ProjectController (line 25) | class ProjectController extends Controller
    method checkPermission (line 27) | protected function checkPermission(Organization $organization, string ...
    method index (line 44) | public function index(Organization $organization, ProjectIndexRequest ...
    method show (line 79) | public function show(Organization $organization, Project $project): Js...
    method store (line 98) | public function store(Organization $organization, ProjectStoreRequest ...
    method update (line 124) | public function update(Organization $organization, Project $project, P...
    method destroy (line 168) | public function destroy(Organization $organization, Project $project):...

FILE: app/Http/Controllers/Api/V1/ProjectMemberController.php
  class ProjectMemberController (line 23) | class ProjectMemberController extends Controller
    method checkPermission (line 25) | protected function checkPermission(Organization $organization, string ...
    method index (line 45) | public function index(Organization $organization, Project $project, Pr...
    method store (line 64) | public function store(Organization $organization, Project $project, Pr...
    method update (line 97) | public function update(Organization $organization, ProjectMember $proj...
    method destroy (line 118) | public function destroy(Organization $organization, ProjectMember $pro...

FILE: app/Http/Controllers/Api/V1/Public/ReportController.php
  class ReportController (line 19) | class ReportController extends Controller
    method show (line 30) | public function show(Request $request, TimeEntryAggregationService $ti...

FILE: app/Http/Controllers/Api/V1/ReportController.php
  class ReportController (line 22) | class ReportController extends Controller
    method checkPermission (line 27) | protected function checkPermission(Organization $organization, string ...
    method index (line 44) | public function index(Organization $organization, ReportIndexRequest $...
    method show (line 63) | public function show(Organization $organization, Report $report): Deta...
    method store (line 77) | public function store(Organization $organization, ReportStoreRequest $...
    method update (line 134) | public function update(Organization $organization, Report $report, Rep...
    method destroy (line 170) | public function destroy(Organization $organization, Report $report): J...

FILE: app/Http/Controllers/Api/V1/TagController.php
  class TagController (line 19) | class TagController extends Controller
    method checkPermission (line 21) | protected function checkPermission(Organization $organization, string ...
    method index (line 38) | public function index(Organization $organization, TagIndexRequest $req...
    method store (line 57) | public function store(Organization $organization, TagStoreRequest $req...
    method update (line 76) | public function update(Organization $organization, Tag $tag, TagUpdate...
    method destroy (line 93) | public function destroy(Organization $organization, Tag $tag): JsonRes...

FILE: app/Http/Controllers/Api/V1/TaskController.php
  class TaskController (line 21) | class TaskController extends Controller
    method checkPermission (line 23) | protected function checkPermission(Organization $organization, string ...
    method checkScopedPermissionForProject (line 36) | private function checkScopedPermissionForProject(Organization $organiz...
    method index (line 60) | public function index(Organization $organization, TaskIndexRequest $re...
    method store (line 99) | public function store(Organization $organization, TaskStoreRequest $re...
    method update (line 129) | public function update(Organization $organization, Task $task, TaskUpd...
    method destroy (line 161) | public function destroy(Organization $organization, Task $task): JsonR...

FILE: app/Http/Controllers/Api/V1/TimeEntryController.php
  class TimeEntryController (line 59) | class TimeEntryController extends Controller
    method assertNoOverlap (line 61) | private function assertNoOverlap(Organization $organization, Member $m...
    method checkPermission (line 98) | protected function checkPermission(Organization $organization, string ...
    method index (line 118) | public function index(Organization $organization, TimeEntryIndexReques...
    method getTimeEntriesQuery (line 183) | private function getTimeEntriesQuery(Organization $organization, TimeE...
    method indexExport (line 220) | public function indexExport(Organization $organization, TimeEntryIndex...
    method aggregate (line 369) | public function aggregate(Organization $organization, TimeEntryAggrega...
    method aggregateExport (line 418) | public function aggregateExport(Organization $organization, TimeEntryA...
    method getTimeEntriesAggregateQuery (line 549) | private function getTimeEntriesAggregateQuery(Organization $organizati...
    method store (line 577) | public function store(Organization $organization, TimeEntryStoreReques...
    method update (line 626) | public function update(Organization $organization, TimeEntry $timeEntr...
    method updateMultiple (line 689) | public function updateMultiple(Organization $organization, TimeEntryUp...
    method destroy (line 789) | public function destroy(Organization $organization, TimeEntry $timeEnt...
    method destroyMultiple (line 820) | public function destroyMultiple(Organization $organization, TimeEntryD...

FILE: app/Http/Controllers/Api/V1/UserController.php
  class UserController (line 10) | class UserController extends Controller
    method me (line 21) | public function me(): UserResource

FILE: app/Http/Controllers/Api/V1/UserMembershipController.php
  class UserMembershipController (line 12) | class UserMembershipController extends Controller
    method myMemberships (line 25) | public function myMemberships(): JsonResource

FILE: app/Http/Controllers/Api/V1/UserTimeEntryController.php
  class UserTimeEntryController (line 15) | class UserTimeEntryController extends Controller
    method myActive (line 24) | public function myActive(): JsonResource

FILE: app/Http/Controllers/Controller.php
  class Controller (line 17) | class Controller extends BaseController
    method user (line 25) | protected function user(): User
    method member (line 40) | protected function member(Organization $organization): Member
    method currentOrganization (line 59) | protected function currentOrganization(): Organization

FILE: app/Http/Controllers/Web/Controller.php
  class Controller (line 7) | abstract class Controller extends \App\Http\Controllers\Controller {}

FILE: app/Http/Controllers/Web/DashboardController.php
  class DashboardController (line 14) | class DashboardController extends Controller
    method dashboard (line 19) | public function dashboard(DashboardService $dashboardService, Permissi...

FILE: app/Http/Controllers/Web/HealthCheckController.php
  class HealthCheckController (line 15) | class HealthCheckController extends Controller
    method up (line 21) | public function up(): JsonResponse
    method debug (line 32) | public function debug(Request $request): JsonResponse

FILE: app/Http/Controllers/Web/HomeController.php
  class HomeController (line 10) | class HomeController extends Controller
    method index (line 12) | public function index(): RedirectResponse

FILE: app/Http/Kernel.php
  class Kernel (line 11) | class Kernel extends HttpKernel

FILE: app/Http/Middleware/Authenticate.php
  class Authenticate (line 10) | class Authenticate extends Middleware
    method redirectTo (line 15) | protected function redirectTo(Request $request): ?string

FILE: app/Http/Middleware/CheckOrganizationBlocked.php
  class CheckOrganizationBlocked (line 14) | class CheckOrganizationBlocked
    method handle (line 23) | public function handle(Request $request, Closure $next): Response

FILE: app/Http/Middleware/EncryptCookies.php
  class EncryptCookies (line 9) | class EncryptCookies extends Middleware

FILE: app/Http/Middleware/EnsureEmailIsVerified.php
  class EnsureEmailIsVerified (line 13) | class EnsureEmailIsVerified
    method handle (line 18) | public function handle(Request $request, Closure $next, ?string $redir...

FILE: app/Http/Middleware/ForceHttps.php
  class ForceHttps (line 12) | class ForceHttps
    method handle (line 19) | public function handle(Request $request, Closure $next, string ...$gua...

FILE: app/Http/Middleware/ForceJsonResponse.php
  class ForceJsonResponse (line 11) | class ForceJsonResponse
    method handle (line 18) | public function handle(Request $request, Closure $next, string ...$gua...

FILE: app/Http/Middleware/HandleInertiaRequests.php
  class HandleInertiaRequests (line 12) | class HandleInertiaRequests extends Middleware
    method version (line 28) | public function version(Request $request): ?string
    method share (line 40) | public function share(Request $request): array

FILE: app/Http/Middleware/PreventRequestsDuringMaintenance.php
  class PreventRequestsDuringMaintenance (line 9) | class PreventRequestsDuringMaintenance extends Middleware

FILE: app/Http/Middleware/RedirectIfAuthenticated.php
  class RedirectIfAuthenticated (line 13) | class RedirectIfAuthenticated
    method handle (line 20) | public function handle(Request $request, Closure $next, string ...$gua...

FILE: app/Http/Middleware/ShareInertiaData.php
  class ShareInertiaData (line 20) | class ShareInertiaData
    method handle (line 25) | public function handle(Request $request, Closure $next): Response

FILE: app/Http/Middleware/TrimStrings.php
  class TrimStrings (line 9) | class TrimStrings extends Middleware

FILE: app/Http/Middleware/TrustProxies.php
  class TrustProxies (line 10) | class TrustProxies extends Middleware

FILE: app/Http/Middleware/ValidateSignature.php
  class ValidateSignature (line 9) | class ValidateSignature extends Middleware

FILE: app/Http/Middleware/VerifyCsrfToken.php
  class VerifyCsrfToken (line 9) | class VerifyCsrfToken extends Middleware

FILE: app/Http/Requests/V1/ApiToken/ApiTokenStoreRequest.php
  class ApiTokenStoreRequest (line 9) | class ApiTokenStoreRequest extends BaseFormRequest
    method rules (line 16) | public function rules(): array
    method getName (line 28) | public function getName(): string

FILE: app/Http/Requests/V1/BaseFormRequest.php
  class BaseFormRequest (line 9) | class BaseFormRequest extends FormRequest
    method moneyRules (line 14) | protected function moneyRules(bool $bigInt = false): array

FILE: app/Http/Requests/V1/Client/ClientIndexRequest.php
  class ClientIndexRequest (line 10) | class ClientIndexRequest extends BaseFormRequest
    method rules (line 17) | public function rules(): array
    method getFilterArchived (line 32) | public function getFilterArchived(): string

FILE: app/Http/Requests/V1/Client/ClientStoreRequest.php
  class ClientStoreRequest (line 17) | class ClientStoreRequest extends BaseFormRequest
    method rules (line 24) | public function rules(): array

FILE: app/Http/Requests/V1/Client/ClientUpdateRequest.php
  class ClientUpdateRequest (line 18) | class ClientUpdateRequest extends BaseFormRequest
    method rules (line 25) | public function rules(): array
    method getIsArchived (line 45) | public function getIsArchived(): bool

FILE: app/Http/Requests/V1/Import/ImportRequest.php
  class ImportRequest (line 10) | class ImportRequest extends BaseFormRequest
    method rules (line 17) | public function rules(): array

FILE: app/Http/Requests/V1/Invitation/InvitationIndexRequest.php
  class InvitationIndexRequest (line 14) | class InvitationIndexRequest extends BaseFormRequest
    method rules (line 21) | public function rules(): array

FILE: app/Http/Requests/V1/Invitation/InvitationStoreRequest.php
  class InvitationStoreRequest (line 16) | class InvitationStoreRequest extends BaseFormRequest
    method rules (line 23) | public function rules(): array
    method getRole (line 39) | public function getRole(): Role
    method getEmail (line 44) | public function getEmail(): string

FILE: app/Http/Requests/V1/Member/MemberDestroyRequest.php
  class MemberDestroyRequest (line 14) | class MemberDestroyRequest extends BaseFormRequest
    method rules (line 21) | public function rules(): array
    method getDeleteRelated (line 31) | public function getDeleteRelated(): bool

FILE: app/Http/Requests/V1/Member/MemberIndexRequest.php
  class MemberIndexRequest (line 14) | class MemberIndexRequest extends BaseFormRequest
    method rules (line 21) | public function rules(): array

FILE: app/Http/Requests/V1/Member/MemberMergeIntoRequest.php
  class MemberMergeIntoRequest (line 17) | class MemberMergeIntoRequest extends BaseFormRequest
    method rules (line 24) | public function rules(): array
    method getMemberId (line 38) | public function getMemberId(): string

FILE: app/Http/Requests/V1/Member/MemberUpdateRequest.php
  class MemberUpdateRequest (line 16) | class MemberUpdateRequest extends BaseFormRequest
    method rules (line 23) | public function rules(): array
    method getBillableRate (line 39) | public function getBillableRate(): ?int
    method getRole (line 46) | public function getRole(): Role

FILE: app/Http/Requests/V1/Organization/OrganizationUpdateRequest.php
  class OrganizationUpdateRequest (line 19) | class OrganizationUpdateRequest extends BaseFormRequest
    method rules (line 26) | public function rules(): array
    method getName (line 66) | public function getName(): ?string
    method getNumberFormat (line 71) | public function getNumberFormat(): ?NumberFormat
    method getCurrencyFormat (line 76) | public function getCurrencyFormat(): ?CurrencyFormat
    method getDateFormat (line 81) | public function getDateFormat(): ?DateFormat
    method getIntervalFormat (line 86) | public function getIntervalFormat(): ?IntervalFormat
    method getTimeFormat (line 91) | public function getTimeFormat(): ?TimeFormat
    method getBillableRate (line 96) | public function getBillableRate(): ?int
    method getEmployeesCanSeeBillableRates (line 103) | public function getEmployeesCanSeeBillableRates(): ?bool
    method getEmployeesCanManageTasks (line 108) | public function getEmployeesCanManageTasks(): ?bool
    method getPreventOverlappingTimeEntries (line 113) | public function getPreventOverlappingTimeEntries(): ?bool

FILE: app/Http/Requests/V1/Project/ProjectIndexRequest.php
  class ProjectIndexRequest (line 10) | class ProjectIndexRequest extends BaseFormRequest
    method rules (line 17) | public function rules(): array
    method getFilterArchived (line 32) | public function getFilterArchived(): string

FILE: app/Http/Requests/V1/Project/ProjectStoreRequest.php
  class ProjectStoreRequest (line 21) | class ProjectStoreRequest extends BaseFormRequest
    method rules (line 28) | public function rules(): array
    method getIsPublic (line 87) | public function getIsPublic(): bool
    method getBillableRate (line 92) | public function getBillableRate(): ?int
    method getEstimatedTime (line 99) | public function getEstimatedTime(): ?int

FILE: app/Http/Requests/V1/Project/ProjectUpdateRequest.php
  class ProjectUpdateRequest (line 22) | class ProjectUpdateRequest extends BaseFormRequest
    method rules (line 29) | public function rules(): array
    method getIsArchived (line 86) | public function getIsArchived(): bool
    method getBillableRate (line 93) | public function getBillableRate(): ?int
    method getEstimatedTime (line 100) | public function getEstimatedTime(): ?int

FILE: app/Http/Requests/V1/ProjectMember/ProjectMemberIndexRequest.php
  class ProjectMemberIndexRequest (line 10) | class ProjectMemberIndexRequest extends BaseFormRequest
    method rules (line 17) | public function rules(): array

FILE: app/Http/Requests/V1/ProjectMember/ProjectMemberStoreRequest.php
  class ProjectMemberStoreRequest (line 17) | class ProjectMemberStoreRequest extends BaseFormRequest
    method rules (line 24) | public function rules(): array
    method getBillableRate (line 43) | public function getBillableRate(): ?int

FILE: app/Http/Requests/V1/ProjectMember/ProjectMemberUpdateRequest.php
  class ProjectMemberUpdateRequest (line 14) | class ProjectMemberUpdateRequest extends BaseFormRequest
    method rules (line 21) | public function rules(): array
    method getBillableRate (line 33) | public function getBillableRate(): ?int

FILE: app/Http/Requests/V1/Report/ReportIndexRequest.php
  class ReportIndexRequest (line 10) | class ReportIndexRequest extends BaseFormRequest
    method rules (line 17) | public function rules(): array

FILE: app/Http/Requests/V1/Report/ReportStoreRequest.php
  class ReportStoreRequest (line 23) | class ReportStoreRequest extends BaseFormRequest
    method rules (line 30) | public function rules(): array
    method getName (line 177) | public function getName(): string
    method getDescription (line 182) | public function getDescription(): ?string
    method getIsPublic (line 187) | public function getIsPublic(): bool
    method getPublicUntil (line 192) | public function getPublicUntil(): ?Carbon
    method getPropertyStart (line 199) | public function getPropertyStart(): Carbon
    method getPropertyEnd (line 209) | public function getPropertyEnd(): Carbon
    method getPropertyActive (line 219) | public function getPropertyActive(): ?bool
    method getPropertyBillable (line 228) | public function getPropertyBillable(): ?bool
    method getPropertyGroup (line 237) | public function getPropertyGroup(): TimeEntryAggregationType
    method getPropertySubGroup (line 242) | public function getPropertySubGroup(): TimeEntryAggregationType
    method getPropertyHistoryGroup (line 247) | public function getPropertyHistoryGroup(): TimeEntryAggregationTypeInt...
    method getPropertyRoundingType (line 252) | public function getPropertyRoundingType(): ?TimeEntryRoundingType
    method getPropertyRoundingMinutes (line 261) | public function getPropertyRoundingMinutes(): ?int

FILE: app/Http/Requests/V1/Report/ReportUpdateRequest.php
  class ReportUpdateRequest (line 15) | class ReportUpdateRequest extends BaseFormRequest
    method rules (line 22) | public function rules(): array
    method getName (line 44) | public function getName(): string
    method getDescription (line 49) | public function getDescription(): ?string
    method getIsPublic (line 54) | public function getIsPublic(): bool
    method getPublicUntil (line 59) | public function getPublicUntil(): ?Carbon

FILE: app/Http/Requests/V1/Tag/TagIndexRequest.php
  class TagIndexRequest (line 10) | class TagIndexRequest extends BaseFormRequest
    method rules (line 17) | public function rules(): array

FILE: app/Http/Requests/V1/Tag/TagStoreRequest.php
  class TagStoreRequest (line 17) | class TagStoreRequest extends BaseFormRequest
    method rules (line 24) | public function rules(): array

FILE: app/Http/Requests/V1/Tag/TagUpdateRequest.php
  class TagUpdateRequest (line 18) | class TagUpdateRequest extends BaseFormRequest
    method rules (line 25) | public function rules(): array

FILE: app/Http/Requests/V1/Task/TaskIndexRequest.php
  class TaskIndexRequest (line 19) | class TaskIndexRequest extends BaseFormRequest
    method rules (line 26) | public function rules(): array
    method getFilterDone (line 53) | public function getFilterDone(): string

FILE: app/Http/Requests/V1/Task/TaskStoreRequest.php
  class TaskStoreRequest (line 19) | class TaskStoreRequest extends BaseFormRequest
    method rules (line 26) | public function rules(): array
    method getEstimatedTime (line 56) | public function getEstimatedTime(): ?int

FILE: app/Http/Requests/V1/Task/TaskUpdateRequest.php
  class TaskUpdateRequest (line 18) | class TaskUpdateRequest extends BaseFormRequest
    method rules (line 25) | public function rules(): array
    method getIsDone (line 51) | public function getIsDone(): bool
    method getEstimatedTime (line 58) | public function getEstimatedTime(): ?int

FILE: app/Http/Requests/V1/TimeEntry/TimeEntryAggregateExportRequest.php
  class TimeEntryAggregateExportRequest (line 29) | class TimeEntryAggregateExportRequest extends BaseFormRequest
    method rules (line 36) | public function rules(): array
    method getDebug (line 204) | public function getDebug(): bool
    method getGroup (line 209) | public function getGroup(): TimeEntryAggregationType
    method getSubGroup (line 214) | public function getSubGroup(): TimeEntryAggregationType
    method getHistoryGroup (line 219) | public function getHistoryGroup(): TimeEntryAggregationType
    method getStart (line 224) | public function getStart(): Carbon
    method getEnd (line 234) | public function getEnd(): Carbon
    method getFormatValue (line 244) | public function getFormatValue(): ExportFormat
    method getRoundingType (line 249) | public function getRoundingType(): ?TimeEntryRoundingType
    method getRoundingMinutes (line 258) | public function getRoundingMinutes(): ?int

FILE: app/Http/Requests/V1/TimeEntry/TimeEntryAggregateRequest.php
  class TimeEntryAggregateRequest (line 27) | class TimeEntryAggregateRequest extends BaseFormRequest
    method rules (line 34) | public function rules(): array
    method getGroup (line 186) | public function getGroup(): ?TimeEntryAggregationType
    method getSubGroup (line 191) | public function getSubGroup(): ?TimeEntryAggregationType
    method getFillGapsInTimeGroups (line 196) | public function getFillGapsInTimeGroups(): bool
    method getStart (line 201) | public function getStart(): ?Carbon
    method getEnd (line 206) | public function getEnd(): ?Carbon
    method getRoundingType (line 211) | public function getRoundingType(): ?TimeEntryRoundingType
    method getRoundingMinutes (line 220) | public function getRoundingMinutes(): ?int

FILE: app/Http/Requests/V1/TimeEntry/TimeEntryDestroyMultipleRequest.php
  class TimeEntryDestroyMultipleRequest (line 14) | class TimeEntryDestroyMultipleRequest extends BaseFormRequest
    method rules (line 21) | public function rules(): array

FILE: app/Http/Requests/V1/TimeEntry/TimeEntryIndexExportRequest.php
  class TimeEntryIndexExportRequest (line 25) | class TimeEntryIndexExportRequest extends TimeEntryIndexRequest
    method rules (line 32) | public function rules(): array
    method getDebug (line 183) | public function getDebug(): bool
    method getStart (line 188) | public function getStart(): Carbon
    method getEnd (line 198) | public function getEnd(): Carbon
    method getOnlyFullDates (line 208) | public function getOnlyFullDates(): bool
    method getFormatValue (line 213) | public function getFormatValue(): ExportFormat
    method getRoundingType (line 218) | public function getRoundingType(): ?TimeEntryRoundingType
    method getRoundingMinutes (line 227) | public function getRoundingMinutes(): ?int

FILE: app/Http/Requests/V1/TimeEntry/TimeEntryIndexRequest.php
  class TimeEntryIndexRequest (line 25) | class TimeEntryIndexRequest extends BaseFormRequest
    method rules (line 32) | public function rules(): array
    method getOnlyFullDates (line 178) | public function getOnlyFullDates(): bool
    method getLimit (line 183) | public function getLimit(): int
    method getOffset (line 188) | public function getOffset(): int
    method getRoundingType (line 193) | public function getRoundingType(): ?TimeEntryRoundingType
    method getRoundingMinutes (line 202) | public function getRoundingMinutes(): ?int

FILE: app/Http/Requests/V1/TimeEntry/TimeEntryStoreRequest.php
  class TimeEntryStoreRequest (line 22) | class TimeEntryStoreRequest extends BaseFormRequest
    method rules (line 29) | public function rules(): array

FILE: app/Http/Requests/V1/TimeEntry/TimeEntryUpdateMultipleRequest.php
  class TimeEntryUpdateMultipleRequest (line 22) | class TimeEntryUpdateMultipleRequest extends BaseFormRequest
    method rules (line 29) | public function rules(): array

FILE: app/Http/Requests/V1/TimeEntry/TimeEntryUpdateRequest.php
  class TimeEntryUpdateRequest (line 22) | class TimeEntryUpdateRequest extends BaseFormRequest
    method rules (line 29) | public function rules(): array

FILE: app/Http/Resources/PaginatedResourceCollection.php
  type PaginatedResourceCollection (line 7) | interface PaginatedResourceCollection {}

FILE: app/Http/Resources/V1/ApiToken/ApiTokenCollection.php
  class ApiTokenCollection (line 9) | class ApiTokenCollection extends ResourceCollection

FILE: app/Http/Resources/V1/ApiToken/ApiTokenResource.php
  class ApiTokenResource (line 14) | class ApiTokenResource extends BaseResource
    method toArray (line 21) | public function toArray(Request $request): array

FILE: app/Http/Resources/V1/ApiToken/ApiTokenWithAccessTokenResource.php
  class ApiTokenWithAccessTokenResource (line 14) | class ApiTokenWithAccessTokenResource extends BaseResource
    method __construct (line 18) | public function __construct(Token $resource, string $accessToken)
    method toArray (line 29) | public function toArray(Request $request): array

FILE: app/Http/Resources/V1/BaseResource.php
  class BaseResource (line 10) | abstract class BaseResource extends JsonResource
    method formatDateTime (line 12) | protected function formatDateTime(?Carbon $carbon): ?string
    method formatDate (line 17) | protected function formatDate(?Carbon $carbon): ?string

FILE: app/Http/Resources/V1/Client/ClientCollection.php
  class ClientCollection (line 10) | class ClientCollection extends ResourceCollection implements PaginatedRe...

FILE: app/Http/Resources/V1/Client/ClientResource.php
  class ClientResource (line 14) | class ClientResource extends BaseResource
    method toArray (line 21) | public function toArray(Request $request): array

FILE: app/Http/Resources/V1/Invitation/InvitationCollection.php
  class InvitationCollection (line 10) | class InvitationCollection extends ResourceCollection implements Paginat...

FILE: app/Http/Resources/V1/Invitation/InvitationResource.php
  class InvitationResource (line 14) | class InvitationResource extends BaseResource
    method toArray (line 21) | public function toArray(Request $request): array

FILE: app/Http/Resources/V1/Member/MemberCollection.php
  class MemberCollection (line 10) | class MemberCollection extends ResourceCollection implements PaginatedRe...

FILE: app/Http/Resources/V1/Member/MemberResource.php
  class MemberResource (line 15) | class MemberResource extends BaseResource
    method toArray (line 22) | public function toArray(Request $request): array

FILE: app/Http/Resources/V1/Member/PersonalMembershipCollection.php
  class PersonalMembershipCollection (line 10) | class PersonalMembershipCollection extends ResourceCollection implements...

FILE: app/Http/Resources/V1/Member/PersonalMembershipResource.php
  class PersonalMembershipResource (line 14) | class PersonalMembershipResource extends BaseResource
    method toArray (line 21) | public function toArray(Request $request): array

FILE: app/Http/Resources/V1/Organization/OrganizationResource.php
  class OrganizationResource (line 20) | class OrganizationResource extends BaseResource
    method __construct (line 29) | public function __construct(Organization $resource, bool $showBillable...
    method toArray (line 41) | public function toArray(Request $request): array

FILE: app/Http/Resources/V1/Project/ProjectCollection.php
  class ProjectCollection (line 12) | class ProjectCollection extends ResourceCollection implements PaginatedR...
    method __construct (line 16) | public function __construct($resource, bool $showBillableRates)
    method collects (line 22) | protected function collects(): ?string
    method toArray (line 32) | public function toArray(Request $request): array

FILE: app/Http/Resources/V1/Project/ProjectResource.php
  class ProjectResource (line 14) | class ProjectResource extends BaseResource
    method __construct (line 18) | public function __construct(Project $resource, bool $showBillableRate)
    method toArray (line 30) | public function toArray(Request $request): array

FILE: app/Http/Resources/V1/ProjectMember/ProjectMemberCollection.php
  class ProjectMemberCollection (line 10) | class ProjectMemberCollection extends ResourceCollection implements Pagi...

FILE: app/Http/Resources/V1/ProjectMember/ProjectMemberResource.php
  class ProjectMemberResource (line 14) | class ProjectMemberResource extends BaseResource
    method toArray (line 21) | public function toArray(Request $request): array

FILE: app/Http/Resources/V1/Report/DetailedReportResource.php
  class DetailedReportResource (line 14) | class DetailedReportResource extends BaseResource
    method toArray (line 21) | public function toArray(Request $request): array

FILE: app/Http/Resources/V1/Report/DetailedWithDataReportResource.php
  class DetailedWithDataReportResource (line 43) | class DetailedWithDataReportResource extends BaseResource
    method __construct (line 59) | public function __construct(Report $resource, array $data, array $hist...
    method toArray (line 71) | public function toArray(Request $request): array

FILE: app/Http/Resources/V1/Report/ReportCollection.php
  class ReportCollection (line 10) | class ReportCollection extends ResourceCollection implements PaginatedRe...

FILE: app/Http/Resources/V1/Report/ReportResource.php
  class ReportResource (line 14) | class ReportResource extends BaseResource
    method toArray (line 21) | public function toArray(Request $request): array

FILE: app/Http/Resources/V1/Tag/TagCollection.php
  class TagCollection (line 10) | class TagCollection extends ResourceCollection implements PaginatedResou...

FILE: app/Http/Resources/V1/Tag/TagResource.php
  class TagResource (line 14) | class TagResource extends BaseResource
    method toArray (line 21) | public function toArray(Request $request): array

FILE: app/Http/Resources/V1/Task/TaskCollection.php
  class TaskCollection (line 10) | class TaskCollection extends ResourceCollection implements PaginatedReso...

FILE: app/Http/Resources/V1/Task/TaskResource.php
  class TaskResource (line 15) | class TaskResource extends BaseResource
    method toArray (line 22) | public function toArray(Request $request): array

FILE: app/Http/Resources/V1/TimeEntry/TimeEntryCollection.php
  class TimeEntryCollection (line 10) | class TimeEntryCollection extends ResourceCollection implements Paginate...

FILE: app/Http/Resources/V1/TimeEntry/TimeEntryResource.php
  class TimeEntryResource (line 14) | class TimeEntryResource extends BaseResource
    method toArray (line 21) | public function toArray(Request $request): array

FILE: app/Http/Resources/V1/User/UserResource.php
  class UserResource (line 15) | class UserResource extends BaseResource
    method toArray (line 22) | public function toArray(Request $request): array

FILE: app/Jobs/RecalculateSpentTimeForProject.php
  class RecalculateSpentTimeForProject (line 16) | class RecalculateSpentTimeForProject implements ShouldDispatchAfterCommi...
    method __construct (line 28) | public function __construct(Project $project)
    method handle (line 38) | public function handle(): void

FILE: app/Jobs/RecalculateSpentTimeForTask.php
  class RecalculateSpentTimeForTask (line 16) | class RecalculateSpentTimeForTask implements ShouldDispatchAfterCommit, ...
    method __construct (line 28) | public function __construct(Task $task)
    method handle (line 38) | public function handle(): void

FILE: app/Jobs/Test/TestJob.php
  class TestJob (line 16) | class TestJob implements ShouldQueue
    method __construct (line 32) | public function __construct(User $user, string $message, bool $fail = ...
    method handle (line 44) | public function handle(): void

FILE: app/Listeners/RemovePlaceholder.php
  class RemovePlaceholder (line 13) | class RemovePlaceholder
    method handle (line 18) | public function handle(TeamMemberAdded $event): void

FILE: app/Mail/AuthApiTokenExpirationReminderMail.php
  class AuthApiTokenExpirationReminderMail (line 14) | class AuthApiTokenExpirationReminderMail extends Mailable
    method __construct (line 27) | public function __construct(Token $token, User $user)
    method build (line 36) | public function build(): self

FILE: app/Mail/AuthApiTokenExpiredMail.php
  class AuthApiTokenExpiredMail (line 14) | class AuthApiTokenExpiredMail extends Mailable
    method __construct (line 27) | public function __construct(Token $token, User $user)
    method build (line 36) | public function build(): self

FILE: app/Mail/OrganizationInvitationMail.php
  class OrganizationInvitationMail (line 13) | class OrganizationInvitationMail extends Mailable
    method __construct (line 24) | public function __construct(OrganizationInvitation $invitation)
    method build (line 32) | public function build(): self

FILE: app/Mail/TimeEntryStillRunningMail.php
  class TimeEntryStillRunningMail (line 14) | class TimeEntryStillRunningMail extends Mailable
    method __construct (line 27) | public function __construct(TimeEntry $timeEntry, User $user)
    method build (line 36) | public function build(): self

FILE: app/Models/Audit.php
  class Audit (line 30) | class Audit extends PackageAuditModel

FILE: app/Models/Client.php
  class Client (line 31) | class Client extends Model implements AuditableContract
    method organization (line 53) | public function organization(): BelongsTo
    method projects (line 61) | public function projects(): HasMany
    method scopeVisibleByEmployee (line 70) | public function scopeVisibleByEmployee(Builder $builder, User $user): ...
    method isArchived (line 81) | protected function isArchived(): Attribute

FILE: app/Models/Concerns/CustomAuditable.php
  type CustomAuditable (line 9) | trait CustomAuditable
    method disableAuditing (line 18) | public function disableAuditing(): void

FILE: app/Models/Concerns/HasUuids.php
  type HasUuids (line 9) | trait HasUuids
    method newUniqueId (line 16) | public function newUniqueId(): string

FILE: app/Models/FailedJob.php
  class FailedJob (line 18) | class FailedJob extends Model

FILE: app/Models/Member.php
  class Member (line 33) | class Member extends JetstreamMembership implements AuditableContract
    method user (line 52) | public function user(): BelongsTo
    method organization (line 60) | public function organization(): BelongsTo
    method timeEntries (line 68) | public function timeEntries(): HasMany
    method projectMembers (line 76) | public function projectMembers(): HasMany

FILE: app/Models/Organization.php
  class Organization (line 55) | class Organization extends JetstreamTeam implements AuditableContract
    method allRealUsers (line 117) | public function allRealUsers(): Collection
    method hasRealUserWithEmail (line 122) | public function hasRealUserWithEmail(string $email): bool
    method users (line 134) | public function users(): BelongsToMany
    method owner (line 151) | public function owner(): BelongsTo
    method members (line 159) | public function members(): HasMany
    method realUsers (line 167) | public function realUsers(): BelongsToMany
    method findOrFail (line 179) | public function findOrFail(string $id, array $columns = ['*']): \Larav...

FILE: app/Models/OrganizationInvitation.php
  class OrganizationInvitation (line 27) | class OrganizationInvitation extends JetstreamTeamInvitation implements ...
    method organization (line 58) | public function organization(): BelongsTo
    method team (line 68) | public function team(): BelongsTo

FILE: app/Models/Passport/AuthCode.php
  class AuthCode (line 20) | class AuthCode extends PassportAuthCode
    method user (line 25) | public function user(): BelongsTo

FILE: app/Models/Passport/Client.php
  class Client (line 26) | class Client extends PassportClient
    method newFactory (line 36) | protected static function newFactory(): Factory

FILE: app/Models/Passport/RefreshToken.php
  class RefreshToken (line 9) | class RefreshToken extends PassportRefreshToken {}

FILE: app/Models/Passport/Token.php
  class Token (line 32) | class Token extends PassportToken
    method client (line 43) | public function client(): BelongsTo
    method user (line 56) | public function user(): BelongsTo
    method casts (line 66) | protected function casts(): array
    method scopeIsApiToken (line 81) | public function scopeIsApiToken(Builder $query, bool $isApiToken = tru...

FILE: app/Models/Project.php
  class Project (line 45) | class Project extends Model implements AuditableContract
    method getSpentTimeComputed (line 96) | public function getSpentTimeComputed(): ?int
    method scopeComputedAttributesGenerate (line 118) | public function scopeComputedAttributesGenerate(Builder $builder, arra...
    method scopeComputedAttributesValidate (line 134) | public function scopeComputedAttributesValidate(Builder $builder, arra...
    method organization (line 142) | public function organization(): BelongsTo
    method client (line 150) | public function client(): BelongsTo
    method members (line 158) | public function members(): HasMany
    method tasks (line 166) | public function tasks(): HasMany
    method timeEntries (line 174) | public function timeEntries(): HasMany
    method scopeVisibleByEmployee (line 182) | public function scopeVisibleByEmployee(Builder $builder, User $user): ...
    method isArchived (line 195) | protected function isArchived(): Attribute

FILE: app/Models/ProjectMember.php
  class ProjectMember (line 32) | class ProjectMember extends Model implements AuditableContract
    method project (line 53) | public function project(): BelongsTo
    method user (line 63) | public function user(): BelongsTo
    method member (line 71) | public function member(): BelongsTo
    method scopeWhereBelongsToOrganization (line 79) | public function scopeWhereBelongsToOrganization(Builder $builder, Orga...

FILE: app/Models/Report.php
  class Report (line 30) | class Report extends Model
    method getShareableLink (line 48) | public function getShareableLink(): ?string
    method organization (line 60) | public function organization(): BelongsTo

FILE: app/Models/Tag.php
  class Tag (line 30) | class Tag extends Model implements AuditableContract
    method organization (line 52) | public function organization(): BelongsTo
    method timeEntries (line 62) | public function timeEntries(): HasManyJson

FILE: app/Models/Task.php
  class Task (line 39) | class Task extends Model implements AuditableContract
    method getSpentTimeComputed (line 79) | public function getSpentTimeComputed(): ?int
    method scopeComputedAttributesGenerate (line 101) | public function scopeComputedAttributesGenerate(Builder $builder, arra...
    method scopeComputedAttributesValidate (line 117) | public function scopeComputedAttributesValidate(Builder $builder, arra...
    method project (line 125) | public function project(): BelongsTo
    method organization (line 133) | public function organization(): BelongsTo
    method timeEntries (line 141) | public function timeEntries(): HasMany
    method scopeVisibleByEmployee (line 150) | public function scopeVisibleByEmployee(Builder $builder, User $user): ...
    method isDone (line 161) | public function isDone(): Attribute

FILE: app/Models/TimeEntry.php
  class TimeEntry (line 53) | class TimeEntry extends Model implements AuditableContract
    method getBillableRateComputed (line 120) | public function getBillableRateComputed(): ?int
    method getClientIdComputed (line 125) | public function getClientIdComputed(): ?string
    method scopeComputedAttributesGenerate (line 137) | public function scopeComputedAttributesGenerate(Builder $builder, arra...
    method scopeComputedAttributesValidate (line 158) | public function scopeComputedAttributesValidate(Builder $builder, arra...
    method getDuration (line 163) | public function getDuration(): ?CarbonInterval
    method scopeHasTag (line 171) | public function scopeHasTag(Builder $builder, Tag $tag): void
    method user (line 179) | public function user(): BelongsTo
    method member (line 187) | public function member(): BelongsTo
    method organization (line 195) | public function organization(): BelongsTo
    method project (line 203) | public function project(): BelongsTo
    method task (line 211) | public function task(): BelongsTo
    method client (line 221) | public function client(): BelongsTo
    method tagsRelation (line 231) | public function tagsRelation(): BelongsToJson

FILE: app/Models/User.php
  class User (line 63) | class User extends Authenticatable implements AuditableContract, Filamen...
    method profilePhotoUrl (line 128) | protected function profilePhotoUrl(): Attribute
    method canAccessPanel (line 137) | public function canAccessPanel(Panel $panel): bool
    method canBeImpersonated (line 142) | public function canBeImpersonated(): bool
    method organizations (line 150) | public function organizations(): BelongsToMany
    method timeEntries (line 165) | public function timeEntries(): HasMany
    method currentOrganization (line 173) | public function currentOrganization(): BelongsTo
    method projectMembers (line 181) | public function projectMembers(): HasMany
    method accessTokens (line 189) | public function accessTokens(): HasMany
    method authCodes (line 197) | public function authCodes(): HasMany
    method scopeActive (line 205) | public function scopeActive(Builder $builder): void
    method scopeBelongsToOrganization (line 214) | public function scopeBelongsToOrganization(Builder $builder, Organizat...

FILE: app/Policies/OrganizationPolicy.php
  class OrganizationPolicy (line 13) | class OrganizationPolicy
    method viewAny (line 20) | public function viewAny(User $user): bool
    method view (line 32) | public function view(User $user, Organization $organization): bool
    method create (line 44) | public function create(User $user): bool
    method update (line 56) | public function update(User $user, Organization $organization): bool
    method addTeamMember (line 68) | public function addTeamMember(User $user, Organization $organization):...
    method updateTeamMember (line 80) | public function updateTeamMember(User $user, Organization $organizatio...
    method removeTeamMember (line 93) | public function removeTeamMember(User $user, Organization $organizatio...
    method delete (line 106) | public function delete(User $user, Organization $organization): bool

FILE: app/Providers/AppServiceProvider.php
  class AppServiceProvider (line 35) | class AppServiceProvider extends ServiceProvider
    method register (line 40) | public function register(): void
    method boot (line 48) | public function boot(): void

FILE: app/Providers/AuthServiceProvider.php
  class AuthServiceProvider (line 17) | class AuthServiceProvider extends ServiceProvider
    method boot (line 31) | public function boot(): void

FILE: app/Providers/EventServiceProvider.php
  class EventServiceProvider (line 13) | class EventServiceProvider extends ServiceProvider
    method boot (line 32) | public function boot(): void
    method shouldDiscoverEvents (line 40) | public function shouldDiscoverEvents(): bool

FILE: app/Providers/Filament/AdminPanelProvider.php
  class AdminPanelProvider (line 31) | class AdminPanelProvider extends PanelProvider
    method panel (line 33) | public function panel(Panel $panel): Panel

FILE: app/Providers/FortifyServiceProvider.php
  class FortifyServiceProvider (line 24) | class FortifyServiceProvider extends ServiceProvider
    method register (line 29) | public function register(): void
    method boot (line 37) | public function boot(): void

FILE: app/Providers/JetstreamServiceProvider.php
  class JetstreamServiceProvider (line 34) | class JetstreamServiceProvider extends ServiceProvider
    method register (line 39) | public function register(): void
    method boot (line 47) | public function boot(): void
    method configurePermissions (line 78) | protected function configurePermissions(): void

FILE: app/Providers/RouteServiceProvider.php
  class RouteServiceProvider (line 14) | class RouteServiceProvider extends ServiceProvider
    method boot (line 28) | public function boot(): void

FILE: app/Providers/TelescopeServiceProvider.php
  class TelescopeServiceProvider (line 13) | class TelescopeServiceProvider extends TelescopeApplicationServiceProvider
    method register (line 18) | public function register(): void
    method hideSensitiveRequestDetails (line 40) | protected function hideSensitiveRequestDetails(): void
    method gate (line 60) | protected function gate(): void

FILE: app/Rules/ColorRule.php
  class ColorRule (line 12) | class ColorRule implements ValidationRule
    method validate (line 19) | public function validate(string $attribute, mixed $value, Closure $fai...

FILE: app/Rules/CurrencyRule.php
  class CurrencyRule (line 12) | class CurrencyRule implements ValidationRule
    method validate (line 19) | public function validate(string $attribute, mixed $value, Closure $fai...

FILE: app/Service/ApiService.php
  class ApiService (line 19) | class ApiService
    method checkForUpdate (line 23) | public function checkForUpdate(): ?string
    method telemetry (line 54) | public function telemetry(): bool

FILE: app/Service/BillableRateService.php
  class BillableRateService (line 14) | class BillableRateService
    method updateTimeEntriesBillableRateForProjectMember (line 16) | public function updateTimeEntriesBillableRateForProjectMember(ProjectM...
    method updateTimeEntriesBillableRateForProject (line 25) | public function updateTimeEntriesBillableRateForProject(Project $proje...
    method updateTimeEntriesBillableRateForMember (line 42) | public function updateTimeEntriesBillableRateForMember(Member $member)...
    method updateTimeEntriesBillableRateForOrganization (line 60) | public function updateTimeEntriesBillableRateForOrganization(Organizat...
    method getBillableRateForTimeEntryWithGivenRelations (line 81) | public function getBillableRateForTimeEntryWithGivenRelations(TimeEntr...
    method getBillableRateForTimeEntry (line 102) | public function getBillableRateForTimeEntry(TimeEntry $timeEntry): ?int

FILE: app/Service/BillingContract.php
  class BillingContract (line 15) | class BillingContract
    method hasSubscription (line 23) | public function hasSubscription(Organization $organization): bool
    method hasTrial (line 32) | public function hasTrial(Organization $organization): bool
    method getTrialUntil (line 41) | public function getTrialUntil(Organization $organization): ?Carbon
    method isBlocked (line 53) | public function isBlocked(Organization $organization): bool

FILE: app/Service/ColorService.php
  class ColorService (line 7) | class ColorService
    method isBuiltInColor (line 36) | public function isBuiltInColor(string $color): bool
    method getRandomColor (line 41) | public function getRandomColor(?string $seed = null): string
    method isValid (line 50) | public function isValid(string $color): bool

FILE: app/Service/CurrencyService.php
  class CurrencyService (line 10) | class CurrencyService
    method getCurrencySymbolForMoney (line 365) | public function getCurrencySymbolForMoney(Money $money): string
    method getCurrencySymbol (line 370) | public function getCurrencySymbol(string $currencyCode): string
    method getRandomCurrencyCode (line 379) | public function getRandomCurrencyCode(): string

FILE: app/Service/DashboardService.php
  class DashboardService (line 19) | class DashboardService
    method __construct (line 23) | public function __construct(TimezoneService $timezoneService)
    method lastDays (line 31) | private function lastDays(int $days, CarbonTimeZone $timeZone): Collec...
    method lastDaysSplitInWindows (line 46) | private function lastDaysSplitInWindows(int $days, CarbonTimeZone $tim...
    method daysOfThisWeek (line 80) | private function daysOfThisWeek(CarbonTimeZone $timeZone, Weekday $sta...
    method constrainDateByPossibleDates (line 98) | private function constrainDateByPossibleDates(Builder $builder, Collec...
    method constrainDateByCurrentWeek (line 123) | private function constrainDateByCurrentWeek(Builder $builder, CarbonTi...
    method getDailyTrackedHours (line 138) | public function getDailyTrackedHours(User $user, Organization $organiz...
    method getWeeklyHistory (line 181) | public function getWeeklyHistory(User $user, Organization $organizatio...
    method totalWeeklyTime (line 217) | public function totalWeeklyTime(User $user, Organization $organization...
    method totalWeeklyBillableTime (line 234) | public function totalWeeklyBillableTime(User $user, Organization $orga...
    method totalWeeklyBillableAmount (line 255) | public function totalWeeklyBillableAmount(User $user, Organization $or...
    method weeklyProjectOverview (line 285) | public function weeklyProjectOverview(User $user, Organization $organi...
    method latestTeamActivity (line 345) | public function latestTeamActivity(Organization $organization): array
    method latestTasks (line 383) | public function latestTasks(User $user, Organization $organization): a...
    method lastSevenDays (line 423) | public function lastSevenDays(User $user, Organization $organization):...

FILE: app/Service/DeletionService.php
  class DeletionService (line 24) | class DeletionService
    method __construct (line 30) | public function __construct(UserService $userService, MemberService $m...
    method deleteOrganization (line 36) | public function deleteOrganization(Organization $organization, bool $i...
    method deleteUser (line 133) | public function deleteUser(User $user, bool $inTransaction = true): void

FILE: app/Service/Dto/ReportPropertiesDto.php
  class ReportPropertiesDto (line 19) | class ReportPropertiesDto implements Castable
    method castUsing (line 74) | public static function castUsing(array $arguments): CastsAttributes
    method idArrayToCollection (line 171) | public static function idArrayToCollection(array $ids): Collection
    method setMemberIds (line 190) | public function setMemberIds(?array $memberIds): void
    method setClientIds (line 198) | public function setClientIds(?array $clientIds): void
    method setProjectIds (line 206) | public function setProjectIds(?array $projectIds): void
    method setTagIds (line 214) | public function setTagIds(?array $tagIds): void
    method setTaskIds (line 222) | public function setTaskIds(?array $taskIds): void

FILE: app/Service/Export/ExportException.php
  class ExportException (line 9) | class ExportException extends ApiException

FILE: app/Service/Export/ExportService.php
  class ExportService (line 30) | class ExportService
    method export (line 37) | public function export(Organization $organization): string

FILE: app/Service/Import/ImportDatabaseHelper.php
  class ImportDatabaseHelper (line 16) | class ImportDatabaseHelper
    method __construct (line 68) | public function __construct(string $model, array $identifiers, bool $a...
    method getModelInstance (line 83) | private function getModelInstance(): Builder
    method createEntity (line 92) | private function createEntity(array $identifierData, array $createValu...
    method getHash (line 132) | private function getHash(array $data): string
    method getKey (line 148) | public function getKey(array $identifierData, array $createValues = []...
    method getModelById (line 174) | public function getModelById(string $id): ?Model
    method getCachedModels (line 194) | public function getCachedModels(): array
    method getModel (line 207) | public function getModel(array $identifierData): ?Model
    method validateIdentifierData (line 229) | private function validateIdentifierData(array $identifierData): void
    method getKeyByExternalIdentifier (line 236) | public function getKeyByExternalIdentifier(string $externalIdentifier)...
    method getExternalIds (line 249) | public function getExternalIds(): array
    method checkMap (line 255) | private function checkMap(): void
    method getCreatedCount (line 280) | public function getCreatedCount(): int

FILE: app/Service/Import/ImportService.php
  class ImportService (line 18) | class ImportService
    method import (line 23) | public function import(Organization $organization, string $importerTyp...

FILE: app/Service/Import/Importers/ClockifyProjectsImporter.php
  class ClockifyProjectsImporter (line 12) | class ClockifyProjectsImporter extends DefaultImporter
    method importData (line 17) | #[\Override]
    method validateHeader (line 76) | private function validateHeader(array $header): void
    method getBillableRateKey (line 96) | private function getBillableRateKey(array $header): ?string
    method getName (line 109) | #[\Override]
    method getDescription (line 115) | #[\Override]

FILE: app/Service/Import/Importers/ClockifyTimeEntriesImporter.php
  class ClockifyTimeEntriesImporter (line 18) | class ClockifyTimeEntriesImporter extends DefaultImporter
    method getTags (line 25) | private function getTags(string $tags): array
    method importData (line 46) | #[\Override]
    method validateHeader (line 211) | private function validateHeader(array $header): void
    method getName (line 235) | #[\Override]
    method getDescription (line 241) | #[\Override]

FILE: app/Service/Import/Importers/DefaultImporter.php
  class DefaultImporter (line 22) | abstract class DefaultImporter implements ImporterContract
    method init (line 74) | public function init(Organization $organization): void
    method getReport (line 184) | #[\Override]

FILE: app/Service/Import/Importers/GenericProjectsImporter.php
  class GenericProjectsImporter (line 15) | class GenericProjectsImporter extends DefaultImporter
    method importData (line 27) | #[Override]
    method validateHeader (line 85) | private function validateHeader(array $header): void
    method getName (line 94) | #[Override]
    method getDescription (line 100) | #[Override]

FILE: app/Service/Import/Importers/GenericTimeEntriesImporter.php
  class GenericTimeEntriesImporter (line 18) | class GenericTimeEntriesImporter extends DefaultImporter
    method getTags (line 41) | private function getTags(string $tags): array
    method importData (line 62) | #[\Override]
    method validateHeader (line 188) | private function validateHeader(array $header): void
    method getName (line 197) | #[\Override]
    method getDescription (line 203) | #[\Override]

FILE: app/Service/Import/Importers/HarvestClientsImporter.php
  class HarvestClientsImporter (line 11) | class HarvestClientsImporter extends DefaultImporter
    method importData (line 23) | #[\Override]
    method validateHeader (line 56) | private function validateHeader(array $header): void
    method getName (line 65) | #[\Override]
    method getDescription (line 71) | #[\Override]

FILE: app/Service/Import/Importers/HarvestProjectsImporter.php
  class HarvestProjectsImporter (line 12) | class HarvestProjectsImporter extends DefaultImporter
    method importData (line 27) | #[\Override]
    method validateHeader (line 87) | private function validateHeader(array $header): void
    method getName (line 96) | #[\Override]
    method getDescription (line 102) | #[\Override]

FILE: app/Service/Import/Importers/HarvestTimeEntriesImporter.php
  class HarvestTimeEntriesImporter (line 19) | class HarvestTimeEntriesImporter extends DefaultImporter
    method importData (line 39) | #[Override]
    method validateHeader (line 171) | private function validateHeader(array $header): void
    method getName (line 180) | #[Override]
    method getDescription (line 186) | #[Override]

FILE: app/Service/Import/Importers/ImportException.php
  class ImportException (line 7) | class ImportException extends \Exception {}

FILE: app/Service/Import/Importers/ImporterContract.php
  type ImporterContract (line 9) | interface ImporterContract
    method init (line 11) | public function init(Organization $organization): void;
    method importData (line 13) | public function importData(string $data, string $timezone): void;
    method getReport (line 15) | public function getReport(): ReportDto;
    method getName (line 17) | public function getName(): string;
    method getDescription (line 19) | public function getDescription(): string;

FILE: app/Service/Import/Importers/ImporterProvider.php
  class ImporterProvider (line 7) | class ImporterProvider
    method registerImporter (line 28) | public function registerImporter(string $type, string $importer): void
    method getImporterKeys (line 36) | public function getImporterKeys(): array
    method getImporters (line 44) | public function getImporters(): array
    method getImporter (line 49) | public function getImporter(string $type): ImporterContract

FILE: app/Service/Import/Importers/ReportDto.php
  class ReportDto (line 7) | class ReportDto
    method __construct (line 21) | public function __construct(int $clientsCreated, int $projectsCreated,...
    method toArray (line 53) | public function toArray(): array

FILE: app/Service/Import/Importers/SolidtimeImporter.php
  class SolidtimeImporter (line 20) | class SolidtimeImporter extends DefaultImporter
    method importData (line 30) | #[Override]
    method getTags (line 329) | private function getTags(string $tags): array
    method getName (line 350) | #[Override]
    method getDescription (line 356) | #[Override]

FILE: app/Service/Import/Importers/TogglDataImporter.php
  class TogglDataImporter (line 18) | class TogglDataImporter extends DefaultImporter
    method importData (line 23) | #[Override]
    method getName (line 212) | #[Override]
    method getDescription (line 218) | #[Override]

FILE: app/Service/Import/Importers/TogglTimeEntriesImporter.php
  class TogglTimeEntriesImporter (line 18) | class TogglTimeEntriesImporter extends DefaultImporter
    method getTags (line 25) | private function getTags(string $tags): array
    method importData (line 46) | #[\Override]
    method validateHeader (line 172) | private function validateHeader(array $header): void
    method getName (line 195) | #[\Override]
    method getDescription (line 201) | #[\Override]

FILE: app/Service/IntervalService.php
  class IntervalService (line 9) | class IntervalService
    method format (line 11) | public function format(CarbonInterval $interval): string

FILE: app/Service/InvitationService.php
  class InvitationService (line 17) | class InvitationService
    method inviteUser (line 22) | public function inviteUser(Organization $organization, string $email, ...

FILE: app/Service/IpLookup/IpLookupResponseDto.php
  class IpLookupResponseDto (line 9) | class IpLookupResponseDto
    method __construct (line 17) | public function __construct(?string $timezone, ?Weekday $startOfWeek, ...

FILE: app/Service/IpLookup/IpLookupServiceContract.php
  type IpLookupServiceContract (line 7) | interface IpLookupServiceContract
    method lookup (line 9) | public function lookup(string $ip): ?IpLookupResponseDto;

FILE: app/Service/IpLookup/NoIpLookupService.php
  class NoIpLookupService (line 7) | class NoIpLookupService implements IpLookupServiceContract
    method lookup (line 9) | public function lookup(string $ip): ?IpLookupResponseDto

FILE: app/Service/LocalizationService.php
  class LocalizationService (line 18) | class LocalizationService
    method __construct (line 30) | public function __construct(CurrencyFormat $currencyFormat, DateFormat...
    method forOrganization (line 39) | public static function forOrganization(Organization $organization): self
    method formatNumber (line 50) | public function formatNumber(BigDecimal|float $number): string
    method formatNumberWithoutTrailingZeros (line 67) | public function formatNumberWithoutTrailingZeros(BigDecimal|float $num...
    method formatInterval (line 78) | public function formatInterval(CarbonInterval $interval): string
    method formatCurrency (line 99) | public function formatCurrency(Money $money): string
    method formatTime (line 117) | public function formatTime(CarbonInterface $time): string
    method formatDate (line 126) | public function formatDate(CarbonInterface $date): string
    method setDateFormat (line 131) | public function setDateFormat(DateFormat $dateFormat): void
    method setCurrencyFormat (line 136) | public function setCurrencyFormat(CurrencyFormat $currencyFormat): void
    method setIntervalFormat (line 141) | public function setIntervalFormat(IntervalFormat $intervalFormat): void
    method setTimeFormat (line 146) | public function setTimeFormat(TimeFormat $timeFormat): void
    method setNumberFormat (line 151) | public function setNumberFormat(NumberFormat $numberFormat): void

FILE: app/Service/MemberService.php
  class MemberService (line 27) | class MemberService
    method __construct (line 31) | public function __construct(UserService $userService)
    method addMember (line 36) | public function addMember(User $user, Organization $organization, Role...
    method removeMember (line 64) | public function removeMember(Member $member, Organization $organizatio...
    method changeRole (line 108) | public function changeRole(Member $member, Organization $organization,...
    method assignOrganizationEntitiesToDifferentMember (line 131) | public function assignOrganizationEntitiesToDifferentMember(Organizati...
    method changeOwnership (line 168) | public function changeOwnership(Organization $organization, Member $ne...
    method makeMemberToPlaceholder (line 189) | public function makeMemberToPlaceholder(Member $member, bool $makeSure...

FILE: app/Service/OrganizationInvitationService.php
  class OrganizationInvitationService (line 11) | class OrganizationInvitationService
    method resend (line 13) | public function resend(OrganizationInvitation $invitation): void

FILE: app/Service/OrganizationService.php
  class OrganizationService (line 16) | class OrganizationService
    method createOrganization (line 18) | public function createOrganization(

FILE: app/Service/PermissionStore.php
  class PermissionStore (line 13) | class PermissionStore
    method clear (line 20) | public function clear(): void
    method has (line 25) | public function has(Organization $organization, string $permission): bool
    method userHas (line 36) | public function userHas(Organization $organization, User $user, string...
    method getPermissionsByUser (line 55) | private function getPermissionsByUser(Organization $organization, User...
    method getPermissions (line 92) | public function getPermissions(Organization $organization): array

FILE: app/Service/ReportExport/CsvExport.php
  class CsvExport (line 19) | abstract class CsvExport
    method __construct (line 44) | public function __construct(string $disk, string $folderPath, string $...
    method mapRow (line 58) | abstract public function mapRow(Model $model): array;
    method export (line 65) | public function export(): void
    method convertRow (line 91) | private function convertRow(array $data): array
    method validateRow (line 112) | private function validateRow(array $row): void

FILE: app/Service/ReportExport/TimeEntriesDetailedCsvExport.php
  class TimeEntriesDetailedCsvExport (line 15) | class TimeEntriesDetailedCsvExport extends CsvExport
    method __construct (line 35) | public function __construct(string $disk, string $folderPath, string $...
    method mapRow (line 45) | public function mapRow(Model $model): array

FILE: app/Service/ReportExport/TimeEntriesDetailedExport.php
  class TimeEntriesDetailedExport (line 27) | class TimeEntriesDetailedExport implements FromQuery, ShouldAutoSize, Wi...
    method __construct (line 45) | public function __construct(Builder $builder, ExportFormat $exportForm...
    method query (line 56) | public function query(): Builder
    method columnFormats (line 64) | public function columnFormats(): array
    method styles (line 85) | public function styles(Worksheet $sheet): array
    method headings (line 96) | public function headings(): array
    method map (line 117) | public function map($model): array

FILE: app/Service/ReportExport/TimeEntriesReportExport.php
  class TimeEntriesReportExport (line 15) | class TimeEntriesReportExport implements FromView, ShouldAutoSize, WithC...
    method __construct (line 71) | public function __construct(array $data, ExportFormat $exportFormat, s...
    method view (line 81) | public function view(): View
    method getCsvSettings (line 96) | public function getCsvSettings(): array

FILE: app/Service/ReportService.php
  class ReportService (line 9) | class ReportService
    method generateSecret (line 11) | public function generateSecret(): string

FILE: app/Service/TimeEntryAggregationService.php
  class TimeEntryAggregationService (line 24) | class TimeEntryAggregationService
    method getAggregatedTimeEntries (line 47) | public function getAggregatedTimeEntries(Builder $timeEntriesQuery, ?T...
    method getAggregatedTimeEntriesWithDescriptions (line 226) | public function getAggregatedTimeEntriesWithDescriptions(Builder $time...
    method loadDescriptorsMap (line 295) | private function loadDescriptorsMap(array $keys, TimeEntryAggregationT...
    method fillGapsInTimeGroups (line 400) | public function fillGapsInTimeGroups(array $data, TimeEntryAggregation...
    method getGroupByQuery (line 478) | private function getGroupByQuery(TimeEntryAggregationType $group, stri...
    method timeSlotsBetween (line 517) | public function timeSlotsBetween(Carbon $start, Carbon $end, string $t...

FILE: app/Service/TimeEntryFilter.php
  class TimeEntryFilter (line 13) | class TimeEntryFilter
    method __construct (line 25) | public function __construct(Builder $builder)
    method addEndFilter (line 30) | public function addEndFilter(?string $dateTime): self
    method addEnd (line 40) | public function addEnd(?Carbon $end): self
    method addStartFilter (line 50) | public function addStartFilter(?string $dateTime): self
    method addStart (line 60) | public function addStart(?Carbon $start): self
    method addActiveFilter (line 70) | public function addActiveFilter(?string $active): self
    method addActive (line 86) | public function addActive(?bool $active): self
    method addMemberIdFilter (line 97) | public function addMemberIdFilter(?Member $member): self
    method addMemberIdsFilter (line 110) | public function addMemberIdsFilter(?array $memberIds): self
    method addBillableFilter (line 120) | public function addBillableFilter(?string $billable): self
    method addBillable (line 136) | public function addBillable(?bool $billable): self
    method addClientIdsFilter (line 149) | public function addClientIdsFilter(?array $clientIds): self
    method addProjectIdsFilter (line 172) | public function addProjectIdsFilter(?array $projectIds): self
    method addTagIdsFilter (line 195) | public function addTagIdsFilter(?array $tagIds): self
    method addTaskIdsFilter (line 220) | public function addTaskIdsFilter(?array $taskIds): self
    method get (line 243) | public function get(): Builder

FILE: app/Service/TimeEntryService.php
  class TimeEntryService (line 11) | class TimeEntryService
    method getStartSelectRawForRounding (line 13) | public function getStartSelectRawForRounding(?TimeEntryRoundingType $r...
    method getEndSelectRawForRounding (line 25) | public function getEndSelectRawForRounding(?TimeEntryRoundingType $rou...

FILE: app/Service/TimezoneService.php
  class TimezoneService (line 12) | class TimezoneService
    method getTimezones (line 279) | public function getTimezones(bool $inclLegacy = false): array
    method getTimezoneFromUser (line 286) | public function getTimezoneFromUser(User $user): CarbonTimeZone
    method getSelectOptions (line 303) | public function getSelectOptions(): array
    method isValid (line 314) | public function isValid(string $timezone): bool
    method mapLegacyTimezone (line 319) | public function mapLegacyTimezone(string $timezone): ?string
    method getShiftFromUtc (line 324) | public function getShiftFromUtc(CarbonTimeZone $timeZone): int

FILE: app/Service/UserService.php
  class UserService (line 23) | class UserService
    method createUser (line 25) | public function createUser(
    method assignOrganizationEntitiesToDifferentUser (line 71) | public function assignOrganizationEntitiesToDifferentUser(Organization...
    method makeSureUserHasAtLeastOneOrganization (line 90) | public function makeSureUserHasAtLeastOneOrganization(User $user): void
    method getOrganizationNameForUserName (line 110) | public function getOrganizationNameForUserName(string $username): string
    method makeSureUserHasCurrentOrganization (line 115) | public function makeSureUserHasCurrentOrganization(User $user): void
    method changeOwnership (line 132) | public function changeOwnership(Organization $organization, User $newO...

FILE: database/factories/AuditFactory.php
  class AuditFactory (line 16) | class AuditFactory extends Factory
    method definition (line 23) | public function definition(): array
    method auditUser (line 50) | public function auditUser(User $user): self
    method auditFor (line 62) | public function auditFor(Model $model): self

FILE: database/factories/ClientFactory.php
  class ClientFactory (line 14) | class ClientFactory extends Factory
    method definition (line 21) | public function definition(): array
    method forOrganization (line 30) | public function forOrganization(Organization $organization): self
    method randomCreatedAt (line 37) | public function randomCreatedAt(): self
    method archived (line 46) | public function archived(): self

FILE: database/factories/MemberFactory.php
  class MemberFactory (line 16) | class MemberFactory extends Factory
    method definition (line 23) | public function definition(): array
    method role (line 33) | public function role(Role $role): static
    method forOrganization (line 42) | public function forOrganization(Organization $organization): static
    method forUser (line 49) | public function forUser(User $user): static
    method unverified (line 59) | public function unverified(): static
    method billableRate (line 68) | public function billableRate(?int $billableRate): self
    method withBillableRate (line 75) | public function withBillableRate(): self
    method attachToOrganization (line 82) | public function attachToOrganization(Organization $organization, array...

FILE: database/factories/OrganizationFactory.php
  class OrganizationFactory (line 20) | class OrganizationFactory extends Factory
    method definition (line 27) | public function definition(): array
    method billableRate (line 44) | public function billableRate(?int $billableRate): self
    method withBillableRate (line 51) | public function withBillableRate(): self
    method withOwner (line 58) | public function withOwner(?User $owner = null): self
    method withFakeId (line 65) | public function withFakeId(): self

FILE: database/factories/OrganizationInvitationFactory.php
  class OrganizationInvitationFactory (line 15) | class OrganizationInvitationFactory extends Factory
    method definition (line 22) | public function definition(): array
    method forOrganization (line 31) | public function forOrganization(Organization $organization): self

FILE: database/factories/Passport/ClientFactory.php
  class ClientFactory (line 15) | class ClientFactory extends BaseClientFactory
    method definition (line 22) | public function definition(): array
    method desktopClient (line 39) | public function desktopClient(): self
    method apiClient (line 47) | public function apiClient(): self
    method personalAccessClient (line 55) | public function personalAccessClient(): self
    method forUser (line 64) | public function forUser(User $user): self

FILE: database/factories/Passport/TokenFactory.php
  class TokenFactory (line 15) | class TokenFactory extends Factory
    method definition (line 22) | public function definition(): array
    method forUser (line 39) | public function forUser(User $user): self
    method forClient (line 48) | public function forClient(Client $client): self

FILE: database/factories/ProjectFactory.php
  class ProjectFactory (line 19) | class ProjectFactory extends Factory
    method definition (line 26) | public function definition(): array
    method withEstimatedTime (line 41) | public function withEstimatedTime(): self
    method billable (line 50) | public function billable(?int $billableRate = null): self
    method createdAt (line 60) | public function createdAt(Carbon $createdAt): self
    method archived (line 69) | public function archived(): self
    method forOrganization (line 78) | public function forOrganization(Organization $organization): self
    method isPublic (line 87) | public function isPublic(): self
    method isPrivate (line 96) | public function isPrivate(): self
    method addMember (line 105) | public function addMember(Member $member, array $attributes = []): self
    method withClient (line 115) | public function withClient(): self
    method forClient (line 124) | public function forClient(?Client $client): self

FILE: database/factories/ProjectMemberFactory.php
  class ProjectMemberFactory (line 16) | class ProjectMemberFactory extends Factory
    method definition (line 23) | public function definition(): array
    method forUser (line 36) | public function forUser(User $user): self
    method forMember (line 45) | public function forMember(Member $member): self
    method forProject (line 55) | public function forProject(Project $project): self

FILE: database/factories/ReportFactory.php
  class ReportFactory (line 20) | class ReportFactory extends Factory
    method definition (line 27) | public function definition(): array
    method randomCreatedAt (line 47) | public function randomCreatedAt(): self
    method public (line 54) | public function public(): self
    method private (line 62) | public function private(): self
    method forOrganization (line 70) | public function forOrganization(Organization $organization): self

FILE: database/factories/TagFactory.php
  class TagFactory (line 14) | class TagFactory extends Factory
    method definition (line 21) | public function definition(): array
    method forOrganization (line 29) | public function forOrganization(Organization $organization): self
    method randomCreatedAt (line 38) | public function randomCreatedAt(): self

FILE: database/factories/TaskFactory.php
  class TaskFactory (line 15) | class TaskFactory extends Factory
    method definition (line 22) | public function definition(): array
    method forProject (line 33) | public function forProject(Project $project): self
    method isDone (line 40) | public function isDone(): self
    method forOrganization (line 47) | public function forOrganization(Organization $organization): self

FILE: database/factories/TimeEntryFactory.php
  class TimeEntryFactory (line 20) | class TimeEntryFactory extends Factory
    method definition (line 27) | public function definition(): array
    method notBillable (line 47) | public function notBillable(): self
    method billableRate (line 56) | public function billableRate(int $billableRate): self
    method withTask (line 66) | public function withTask(Organization $organization): self
    method withTags (line 79) | public function withTags(Organization $organization): self
    method startBetween (line 91) | public function startBetween(Carbon $rangeStart, Carbon $rangeEnd, boo...
    method active (line 105) | public function active(): self
    method forUser (line 117) | public function forUser(User $user): self
    method forMember (line 126) | public function forMember(Member $member): static
    method billable (line 137) | public function billable(): self
    method startWithDuration (line 146) | public function startWithDuration(Carbon $start, int $durationInSecond...
    method endWithDuration (line 156) | public function endWithDuration(Carbon $end, int $durationInSeconds): ...
    method start (line 166) | public function start(Carbon $start): self
    method forOrganization (line 175) | public function forOrganization(Organization $organization): self
    method forProject (line 184) | public function forProject(?Project $project): self
    method forTask (line 192) | public function forTask(?Task $task): self

FILE: database/factories/UserFactory.php
  class UserFactory (line 18) | class UserFactory extends Factory
    method definition (line 25) | public function definition(): array
    method forCurrentOrganization (line 44) | public function forCurrentOrganization(Organization $organization): st...
    method randomTimeZone (line 53) | public function randomTimeZone(): static
    method placeholder (line 62) | public function placeholder(bool $placeholder = true): static
    method unverified (line 74) | public function unverified(): static
    method attachToOrganization (line 83) | public function attachToOrganization(Organization $organization, array...
    method withProfilePicture (line 90) | public function withProfilePicture(): static
    method withPersonalOrganization (line 107) | public function withPersonalOrganization(?callable $callback = null): ...

FILE: database/migrations/2014_10_12_000000_create_users_table.php
  method up (line 14) | public function up(): void
  method down (line 46) | public function down(): void

FILE: database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php
  method up (line 14) | public function up(): void
  method down (line 26) | public function down(): void

FILE: database/migrations/2014_10_12_200000_add_two_factor_columns_to_users_table.php
  method up (line 15) | public function up(): void
  method down (line 37) | public function down(): void

FILE: database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php
  method up (line 14) | public function up(): void
  method down (line 29) | public function down(): void

FILE: database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php
  method up (line 14) | public function up(): void
  method down (line 31) | public function down(): void

FILE: database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php
  method up (line 14) | public function up(): void
  method down (line 27) | public function down(): void

FILE: database/migrations/2016_06_01_000004_create_oauth_clients_table.php
  method up (line 14) | public function up(): void
  method down (line 33) | public function down(): void

FILE: database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php
  method up (line 14) | public function up(): void
  method down (line 26) | public function down(): void

FILE: database/migrations/2018_08_08_100000_create_telescope_entries_table.php
  method getConnection (line 14) | public function getConnection(): ?string
  method up (line 22) | public function up(): void
  method down (line 67) | public function down(): void

FILE: database/migrations/2019_08_19_000000_create_failed_jobs_table.php
  method up (line 14) | public function up(): void
  method down (line 30) | public function down(): void

FILE: database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php
  method up (line 14) | public function up(): void
  method down (line 31) | public function down(): void

FILE: database/migrations/2020_05_21_100000_create_organizations_table.php
  method up (line 14) | public function up(): void
  method down (line 30) | public function down(): void

FILE: database/migrations/2020_05_21_200000_create_organization_user_table.php
  method up (line 14) | public function up(): void
  method down (line 31) | public function down(): void

FILE: database/migrations/2020_05_21_300000_create_organization_invitations_table.php
  method up (line 14) | public function up(): void
  method down (line 32) | public function down(): void

FILE: database/migrations/2024_01_16_161030_create_sessions_table.php
  method up (line 14) | public function up(): void
  method down (line 29) | public function down(): void

FILE: database/migrations/2024_01_20_110218_create_clients_table.php
  method up (line 14) | public function up(): void
  method down (line 32) | public function down(): void

FILE: database/migrations/2024_01_20_110439_create_projects_table.php
  method up (line 14) | public function up(): void
  method down (line 41) | public function down(): void

FILE: database/migrations/2024_01_20_110444_create_tasks_table.php
  method up (line 14) | public function up(): void
  method down (line 38) | public function down(): void

FILE: database/migrations/2024_01_20_110452_create_tags_table.php
  method up (line 14) | public function up(): void
  method down (line 34) | public function down(): void

FILE: database/migrations/2024_01_20_110837_create_time_entries_table.php
  method up (line 14) | public function up(): void
  method down (line 59) | public function down(): void

FILE: database/migrations/2024_03_26_171253_create_project_members_table.php
  method up (line 14) | public function up(): void
  method down (line 39) | public function down(): void

FILE: database/migrations/2024_04_11_150130_create_jobs_table.php
  method up (line 14) | public function up(): void
  method down (line 30) | public function down(): void

FILE: database/migrations/2024_04_12_095010_create_cache_table.php
  method up (line 14) | public function up(): void
  method down (line 32) | public function down(): void

FILE: database/migrations/2024_05_07_134711_move_from_user_id_to_member_id_in_project_members_table.php
  method up (line 15) | public function up(): void
  method down (line 39) | public function down(): void

FILE: database/migrations/2024_05_07_141842_move_from_user_id_to_member_id_in_time_entries_table.php
  method up (line 15) | public function up(): void
  method down (line 40) | public function down(): void

FILE: database/migrations/2024_05_13_171020_rename_table_organization_user_to_members.php
  method up (line 13) | public function up(): void
  method down (line 21) | public function down(): void

FILE: database/migrations/2024_05_22_151226_add_client_id_to_time_entries_table.php
  method up (line 15) | public function up(): void
  method down (line 36) | public function down(): void

FILE: database/migrations/2024_05_30_175801_add_is_billable_column_to_projects_table.php
  method up (line 15) | public function up(): void
  method down (line 33) | public function down(): void

FILE: database/migrations/2024_05_30_175825_add_is_imported_column_to_time_entries_table.php
  method up (line 14) | public function up(): void
  method down (line 24) | public function down(): void

FILE: database/migrations/2024_06_01_000001_create_oauth_device_codes_table.php
  method up (line 14) | public function up(): void
  method down (line 32) | public function down(): void
  method getConnection (line 40) | public function getConnection(): ?string

FILE: database/migrations/2024_06_07_113443_change_member_id_foreign_keys_to_restrict_on_delete.php
  method up (line 14) | public function up(): void
  method down (line 51) | public function down(): void

FILE: database/migrations/2024_06_10_161831_reset_billable_rates_with_zero_as_value.php
  method up (line 12) | public function up(): void
  method down (line 34) | public function down(): void

FILE: database/migrations/2024_06_21_122754_add_is_archived_columns_to_projects_and_clients_table.php
  method up (line 14) | public function up(): void
  method down (line 27) | public function down(): void

FILE: database/migrations/2024_06_24_114433_add_done_at_to_tasks_table.php
  method up (line 14) | public function up(): void
  method down (line 24) | public function down(): void

FILE: database/migrations/2024_07_02_134307_add_estimated_time_to_projects_and_tasks_table.php
  method up (line 14) | public function up(): void
  method down (line 27) | public function down(): void

FILE: database/migrations/2024_07_03_145445_change_data_type_of_id_column_in_failed_jobs_table.php
  method up (line 14) | public function up(): void
  method down (line 28) | public function down(): void

FILE: database/migrations/2024_07_18_080906_add_still_active_email_sent_at_to_time_entries_table.php
  method up (line 14) | public function up(): void
  method down (line 24) | public function down(): void

FILE: database/migrations/2024_08_01_104840_create_reports_table.php
  method up (line 14) | public function up(): void
  method down (line 37) | public function down(): void

FILE: database/migrations/2024_09_02_094105_create_audits_table.php
  class CreateAuditsTable (line 9) | class CreateAuditsTable extends Migration
    method up (line 14) | public function up(): void
    method down (line 43) | public function down(): void

FILE: database/migrations/2024_09_18_120203_add_spent_time_to_projects_and_tasks_table.php
  method up (line 14) | public function up(): void
  method down (line 27) | public function down(): void

FILE: database/migrations/2024_10_01_143608_add_employees_can_see_billable_rates_to_organizations_table.php
  method up (line 14) | public function up(): void
  method down (line 24) | public function down(): void

FILE: database/migrations/2024_11_04_164807_add_foreign_key_to_organizations_and_members_table.php
  method up (line 15) | public function up(): void
  method down (line 83) | public function down(): void

FILE: database/migrations/2024_11_04_170614_add_foreign_keys_to_oauth_tables.php
  method up (line 15) | public function up(): void
  method down (line 97) | public function down(): void

FILE: database/migrations/2025_04_03_101827_add_localization_columns_to_organizations_table.php
  method up (line 14) | public function up(): void
  method down (line 36) | public function down(): void

FILE: database/migrations/2025_04_25_202047_change_data_type_for_spent_time_columns.php
  method up (line 14) | public function up(): void
  method down (line 27) | public function down(): void

FILE: database/migrations/2025_05_06_152804_fix_typos_in_organizations_table_format_columns.php
  method up (line 12) | public function up(): void
  method down (line 30) | public function down(): void

FILE: database/migrations/2025_05_16_075757_add_foreign_key_for_current_team_id_in_users_table.php
  method up (line 14) | public function up(): void
  method down (line 37) | public function down(): void

FILE: database/migrations/2025_06_30_095942_remove_oauth_personal_access_clients_table.php
  method up (line 14) | public function up(): void
  method down (line 22) | public function down(): void

FILE: database/migrations/2025_06_30_132538_update_oauth_clients_table.php
  method up (line 14) | public function up(): void
  method down (line 78) | public function down(): void

FILE: database/migrations/2025_07_15_105949_hash_oauth_clients.php
  method up (line 12) | public function up(): void
  method down (line 31) | public function down(): void

FILE: database/migrations/2025_07_17_104903_add_reminder_sent_at_to_oauth_access_tokens_table.php
  method up (line 14) | public function up(): void
  method down (line 25) | public function down(): void

FILE: database/migrations/2025_10_02_000001_add_prevent_overlapping_time_entries_to_organizations_table.php
  method up (line 14) | public function up(): void
  method down (line 24) | public function down(): void

FILE: database/migrations/2025_10_16_000001_extend_time_entry_description.php
  method up (line 14) | public function up(): void
  method down (line 24) | public function down(): void

FILE: database/migrations/2025_10_24_120845_add_employees_can_manage_tasks_to_organizations_table.php
  method up (line 14) | public function up(): void
  method down (line 24) | public function down(): void

FILE: database/schema/pgsql_test-schema.sql
  type public (line 27) | CREATE TABLE public.cache (
  type public (line 38) | CREATE TABLE public.cache_locks (
  type public (line 49) | CREATE TABLE public.clients (
  type public (line 62) | CREATE TABLE public.customers (
  type public (line 80) | CREATE TABLE public.failed_jobs (
  type public (line 95) | CREATE TABLE public.jobs (
  type public (line 129) | CREATE TABLE public.members (
  type public (line 144) | CREATE TABLE public.migrations (
  type public (line 175) | CREATE TABLE public.oauth_access_tokens (
  type public (line 192) | CREATE TABLE public.oauth_auth_codes (
  type public (line 206) | CREATE TABLE public.oauth_clients (
  type public (line 225) | CREATE TABLE public.oauth_personal_access_clients (
  type public (line 256) | CREATE TABLE public.oauth_refresh_tokens (
  type public (line 268) | CREATE TABLE public.organization_invitations (
  type public (line 282) | CREATE TABLE public.organizations (
  type public (line 298) | CREATE TABLE public.password_reset_tokens (
  type public (line 309) | CREATE TABLE public.personal_access_tokens (
  type public (line 327) | CREATE TABLE public.project_members (
  type public (line 342) | CREATE TABLE public.projects (
  type public (line 360) | CREATE TABLE public.sessions (
  type public (line 374) | CREATE TABLE public.subscription_items (
  type public (line 390) | CREATE TABLE public.subscriptions (
  type public (line 409) | CREATE TABLE public.tags (
  type public (line 422) | CREATE TABLE public.tasks (
  type public (line 436) | CREATE TABLE public.time_entries (
  type public (line 460) | CREATE TABLE public.transactions (
  type public (line 481) | CREATE TABLE public.users (
  type customers_billable_id_billable_type_index (line 815) | CREATE INDEX customers_billable_id_billable_type_index ON public.custome...
  type jobs_queue_index (line 822) | CREATE INDEX jobs_queue_index ON public.jobs USING btree (queue)
  type oauth_access_tokens_user_id_index (line 829) | CREATE INDEX oauth_access_tokens_user_id_index ON public.oauth_access_to...
  type oauth_auth_codes_user_id_index (line 836) | CREATE INDEX oauth_auth_codes_user_id_index ON public.oauth_auth_codes U...
  type oauth_clients_user_id_index (line 843) | CREATE INDEX oauth_clients_user_id_index ON public.oauth_clients USING b...
  type oauth_refresh_tokens_access_token_id_index (line 850) | CREATE INDEX oauth_refresh_tokens_access_token_id_index ON public.oauth_...
  type organizations_user_id_index (line 857) | CREATE INDEX organizations_user_id_index ON public.organizations USING b...
  type personal_access_tokens_tokenable_type_tokenable_id_index (line 864) | CREATE INDEX personal_access_tokens_tokenable_type_tokenable_id_index ON...
  type sessions_last_activity_index (line 871) | CREATE INDEX sessions_last_activity_index ON public.sessions USING btree...
  type sessions_user_id_index (line 878) | CREATE INDEX sessions_user_id_index ON public.sessions USING btree (user...
  type subscriptions_billable_id_billable_type_index (line 885) | CREATE INDEX subscriptions_billable_id_billable_type_index ON public.sub...
  type tags_created_at_index (line 892) | CREATE INDEX tags_created_at_index ON public.tags USING btree (created_at)
  type time_entries_billable_index (line 899) | CREATE INDEX time_entries_billable_index ON public.time_entries USING bt...
  type time_entries_end_index (line 906) | CREATE INDEX time_entries_end_index ON public.time_entries USING btree (...
  type time_entries_start_index (line 913) | CREATE INDEX time_entries_start_index ON public.time_entries USING btree...
  type transactions_billable_id_billable_type_index (line 920) | CREATE INDEX transactions_billable_id_billable_type_index ON public.tran...
  type transactions_paddle_subscription_id_index (line 927) | CREATE INDEX transactions_paddle_subscription_id_index ON public.transac...
  type users_email_unique (line 934) | CREATE UNIQUE INDEX users_email_unique ON public.users USING btree (emai...

FILE: database/seeders/DatabaseSeeder.php
  class DatabaseSeeder (line 30) | class DatabaseSeeder extends Seeder
    method run (line 35) | public function run(): void
    method deleteAll (line 202) | private function deleteAll(): void

FILE: e2e/auth.spec.ts
  function registerNewUser (line 5) | async function registerNewUser(page, email, password) {

FILE: e2e/calendar-settings.spec.ts
  function goToCalendar (line 6) | async function goToCalendar(page: Page) {
  function openSettingsPopover (line 11) | async function openSettingsPopover(page: Page) {
  function clearCalendarSettings (line 16) | async function clearCalendarSettings(page: Page) {

FILE: e2e/calendar.spec.ts
  function goToCalendar (line 12) | async function goToCalendar(page: Page) {

FILE: e2e/clients.spec.ts
  function goToClientsOverview (line 13) | async function goToClientsOverview(page: Page) {
  function clearClientTableState (line 139) | async function clearClientTableState(page: Page) {

FILE: e2e/command-palette.spec.ts
  constant TIMER_BUTTON_SELECTOR (line 5) | const TIMER_BUTTON_SELECTOR = '[data-testid="dashboard_timer"] [data-tes...
  function goToDashboard (line 7) | async function goToDashboard(page: Page) {
  function openCommandPalette (line 11) | async function openCommandPalette(page: Page) {
  function closeCommandPalette (line 16) | async function closeCommandPalette(page: Page) {
  function searchInCommandPalette (line 21) | async function searchInCommandPalette(page: Page, query: string) {
  function selectCommand (line 27) | async function selectCommand(page: Page, name: string) {
  function assertTimerIsRunning (line 33) | async function assertTimerIsRunning(page: Page) {
  function assertTimerIsStopped (line 42) | async function assertTimerIsStopped(page: Page) {

FILE: e2e/dashboard.spec.ts
  function goToDashboard (line 18) | async function goToDashboard(page: Page) {

FILE: e2e/import-export.spec.ts
  function goToImportExport (line 6) | async function goToImportExport(page: Page) {

FILE: e2e/members.spec.ts
  function goToMembersPage (line 19) | async function goToMembersPage(page: Page) {
  function openInviteMemberModal (line 23) | async function openInviteMemberModal(page: Page) {
  function clearMemberTableState (line 631) | async function clearMemberTableState(page: Page) {

FILE: e2e/organization.spec.ts
  function goToOrganizationSettings (line 4) | async function goToOrganizationSettings(page) {
  function createTimeEntry (line 10) | async function createTimeEntry(page, duration: string) {

FILE: e2e/profile.spec.ts
  function goToProfilePage (line 5) | async function goToProfilePage(page: Page) {
  function createNewApiToken (line 30) | async function createNewApiToken(page) {

FILE: e2e/project-members.spec.ts
  function createProjectWithMemberViaApi (line 8) | async function createProjectWithMemberViaApi(ctx: TestContext, page: Pag...

FILE: e2e/projects.spec.ts
  function goToProjectsOverview (line 16) | async function goToProjectsOverview(page: Page) {
  function clearProjectTableState (line 21) | async function clearProjectTableState(page: Page) {
  function selectStatusFilter (line 65) | async function selectStatusFilter(page: Page, status: 'Active' | 'Archiv...
  function removeStatusFilter (line 75) | async function removeStatusFilter(page: Page) {

FILE: e2e/shared-reports.spec.ts
  constant DATE_PICKER_BUTTON_PATTERN (line 26) | const DATE_PICKER_BUTTON_PATTERN =

FILE: e2e/tags.spec.ts
  function goToTagsOverview (line 8) | async function goToTagsOverview(page: Page) {
  function clearTagTableState (line 97) | async function clearTagTableState(page: Page) {

FILE: e2e/tasks.spec.ts
  function goToProjectsOverview (line 13) | async function goToProjectsOverview(page: Page) {

FILE: e2e/time.spec.ts
  constant DATE_PICKER_BUTTON_PATTERN (line 22) | const DATE_PICKER_BUTTON_PATTERN =
  constant DATE_DISPLAY_PATTERN (line 25) | const DATE_DISPLAY_PATTERN = /^\d{4}-\d{2}-\d{2}$|^\d{2}\/\d{2}\/\d{4}$|...
  function getDayFromTimestamp (line 30) | function getDayFromTimestamp(timestamp: string): number {
  function getMonthFromTimestamp (line 37) | function getMonthFromTimestamp(timestamp: string): number {
  function goToTimeOverview (line 41) | async function goToTimeOverview(page: Page) {
  function goToOrganizationSettings (line 45) | async function goToOrganizationSettings(page: Page) {
  function createEmptyTimeEntry (line 51) | async function createEmptyTimeEntry(page: Page) {
  function assertThatTimeEntryRowIsStopped (line 88) | async function assertThatTimeEntryRowIsStopped(newTimeEntry: Locator) {

FILE: e2e/timetracker.spec.ts
  constant DATE_DISPLAY_PATTERN (line 15) | const DATE_DISPLAY_PATTERN = /^\d{4}-\d{2}-\d{2}$|^\d{2}\/\d{2}\/\d{4}$|...
  function goToDashboard (line 17) | async function goToDashboard(page: Page) {

FILE: e2e/utils/api.ts
  type TestContext (line 9) | interface TestContext {
  function createApiToken (line 30) | async function createApiToken(page: Page): Promise<string> {
  function bearerHeaders (line 68) | function bearerHeaders(token: string): Record<string, string> {
  function setupTestContext (line 79) | async function setupTestContext(page: Page): Promise<TestContext> {
  function createAuthenticatedRequest (line 89) | function createAuthenticatedRequest(
  function getOrganizationId (line 118) | async function getOrganizationId(
  function getCurrentMemberId (line 130) | async function getCurrentMemberId(
  function parseDurationToSeconds (line 148) | function parseDurationToSeconds(duration: string): number {
  function createTimestamps (line 173) | function createTimestamps(duration: string): { start: string; end: strin...
  function formatTimestamp (line 185) | function formatTimestamp(date: Date): string {
  function randomColor (line 189) | function randomColor(): string {
  function createPublicProjectViaApi (line 207) | async function createPublicProjectViaApi(
  function createProjectViaApi (line 222) | async function createProjectViaApi(
  function archiveProjectViaApi (line 253) | async function archiveProjectViaApi(
  function createBillableProjectViaApi (line 284) | async function createBillableProjectViaApi(
  function createClientViaApi (line 295) | async function createClientViaApi(ctx: TestContext, data: { name: string...
  function createProjectWithClientViaApi (line 305) | async function createProjectWithClientViaApi(
  function createTaskViaApi (line 318) | async function createTaskViaApi(
  function createTagViaApi (line 336) | async function createTagViaApi(ctx: TestContext, data: { name: string }) {
  function createTimeEntryViaApi (line 346) | async function createTimeEntryViaApi(
  function createProjectMemberViaApi (line 378) | async function createProjectMemberViaApi(
  function getMembersViaApi (line 397) | async function getMembersViaApi(ctx: TestContext) {
  function updateMemberBillableRateViaApi (line 413) | async function updateMemberBillableRateViaApi(
  function createTimeEntryWithProjectViaApi (line 431) | async function createTimeEntryWithProjectViaApi(
  function createTimeEntryWithProjectAndTaskViaApi (line 445) | async function createTimeEntryWithProjectAndTaskViaApi(
  function createTimeEntryWithTagViaApi (line 462) | async function createTimeEntryWithTagViaApi(
  function createBareTimeEntryViaApi (line 476) | async function createBareTimeEntryViaApi(
  function createTimeEntryWithBillableStatusViaApi (line 484) | async function createTimeEntryWithBillableStatusViaApi(
  function createPlaceholderMemberViaImportApi (line 500) | async function createPlaceholderMemberViaImportApi(
  function updateOrganizationSettingViaApi (line 529) | async function updateOrganizationSettingViaApi(
  function updateOrganizationCurrencyViaWeb (line 542) | async function updateOrganizationCurrencyViaWeb(
  function createMultipleTimeEntriesViaApi (line 563) | async function createMultipleTimeEntriesViaApi(
  function getInvitationsViaApi (line 583) | async function getInvitationsViaApi(ctx: TestContext) {

FILE: e2e/utils/currentTimeEntry.ts
  function startOrStopTimerWithButton (line 4) | async function startOrStopTimerWithButton(page: Page) {
  function assertThatTimerHasStarted (line 12) | async function assertThatTimerHasStarted(page: Page) {
  function newTimeEntryResponse (line 21) | function newTimeEntryResponse(
  function assertThatTimerIsStopped (line 42) | async function assertThatTimerIsStopped(page: Page) {
  function stoppedTimeEntryResponse (line 51) | async function stoppedTimeEntryResponse(page: Page, { description = '', ...

FILE: e2e/utils/mailpit.ts
  function searchEmails (line 8) | async function searchEmails(
  function getMessage (line 19) | async function getMessage(
  function getInvitationAcceptUrl (line 31) | async function getInvitationAcceptUrl(
  function getPasswordResetUrl (line 59) | async function getPasswordResetUrl(

FILE: e2e/utils/members.ts
  function registerUser (line 10) | async function registerUser(
  function inviteAndAcceptMember (line 41) | async function inviteAndAcceptMember(
  function setupAdminUser (line 75) | async function setupAdminUser(
  function setupEmployeeUser (line 162) | async function setupEmployeeUser(

FILE: e2e/utils/money.ts
  function formatCentsWithOrganizationDefaults (line 5) | function formatCentsWithOrganizationDefaults(

FILE: e2e/utils/reporting.ts
  function goToReporting (line 9) | async function goToReporting(page: Page) {
  function goToReportingDetailed (line 13) | async function goToReportingDetailed(page: Page) {
  function createProject (line 21) | async function createProject(page: Page, projectName: string) {
  function createBillableProject (line 38) | async function createBillableProject(page: Page, projectName: string) {
  function createClient (line 57) | async function createClient(page: Page, clientName: string) {
  function createProjectWithClient (line 74) | async function createProjectWithClient(page: Page, projectName: string, ...
  function createTask (line 96) | async function createTask(page: Page, projectName: string, taskName: str...
  function createTimeEntryWithProject (line 118) | async function createTimeEntryWithProject(
  function createTimeEntryWithProjectAndTask (line 147) | async function createTimeEntryWithProjectAndTask(
  function createTimeEntryWithTag (line 184) | async function createTimeEntryWithTag(page: Page, tagName: string, durat...
  function createBareTimeEntry (line 217) | async function createBareTimeEntry(page: Page, description: string, dura...
  function createTimeEntryWithBillableStatus (line 236) | async function createTimeEntryWithBillableStatus(
  function waitForReportingUpdate (line 275) | async function waitForReportingUpdate(page: Page) {
  function waitForDetailedReportingUpdate (line 282) | async function waitForDetailedReportingUpdate(page: Page) {
  function goToReportingShared (line 296) | async function goToReportingShared(page: Page) {
  function saveAsSharedReport (line 300) | async function saveAsSharedReport(

FILE: e2e/utils/table.ts
  function getTableRowNames (line 7) | async function getTableRowNames(table: Locator): Promise<string[]> {

FILE: e2e/utils/tags.ts
  function newTagResponse (line 3) | function newTagResponse(page: Page, { name = '' } = {}) {

FILE: playwright/config.ts
  constant PLAYWRIGHT_BASE_URL (line 1) | const PLAYWRIGHT_BASE_URL = process.env.PLAYWRIGHT_BASE_URL ?? 'http://s...
  constant MAILPIT_BASE_URL (line 2) | const MAILPIT_BASE_URL = process.env.MAILPIT_BASE_URL ?? 'http://mailpit...
  constant TEST_USER_PASSWORD (line 3) | const TEST_USER_PASSWORD = 'amazingpassword123';

FILE: playwright/fixtures.ts
  type EmployeeFixture (line 10) | interface EmployeeFixture {
  type AdminFixture (line 15) | interface AdminFixture {

FILE: resources/js/Components/Common/Project/constants.ts
  constant NO_CLIENT_ID (line 1) | const NO_CLIENT_ID = '__no_client__';

FILE: resources/js/app.ts
  method setup (line 43) | setup({ el, App, props, plugin }) {

FILE: resources/js/lib/utils.ts
  function cn (line 4) | function cn(...inputs: ClassValue[]) {

FILE: resources/js/packages/api/src/index.ts
  type SolidTimeApi (line 9) | type SolidTimeApi = ApiOf<typeof api>;
  type InvitationsIndexResponse (line 11) | type InvitationsIndexResponse = ZodiosResponseByAlias<SolidTimeApi, 'get...
  type CreateInvitationBody (line 13) | type CreateInvitationBody = ZodiosBodyByAlias<SolidTimeApi, 'invite'>;
  type Invitation (line 15) | type Invitation = InvitationsIndexResponse['data'][0];
  type TimeEntryResponse (line 17) | type TimeEntryResponse = ZodiosResponseByAlias<SolidTimeApi, 'getTimeEnt...
  type TimeEntry (line 18) | type TimeEntry = TimeEntryResponse['data'][0];
  type CreateTimeEntryBody (line 20) | type CreateTimeEntryBody = ZodiosBodyByAlias<SolidTimeApi, 'createTimeEn...
  type UpdateMultipleTimeEntriesBody (line 22) | type UpdateMultipleTimeEntriesBody = ZodiosBodyByAlias<
  type UpdateMultipleTimeEntriesChangeset (line 27) | type UpdateMultipleTimeEntriesChangeset = UpdateMultipleTimeEntriesBody[...
  type ProjectResponse (line 29) | type ProjectResponse = ZodiosResponseByAlias<SolidTimeApi, 'getProjects'>;
  type Project (line 30) | type Project = ProjectResponse['data'][0];
  type CreateProjectBody (line 32) | type CreateProjectBody = ZodiosBodyByAlias<SolidTimeApi, 'createProject'>;
  type UpdateProjectBody (line 34) | type UpdateProjectBody = ZodiosBodyByAlias<SolidTimeApi, 'updateProject'>;
  type ProjectMemberResponse (line 36) | type ProjectMemberResponse = ZodiosResponseByAlias<SolidTimeApi, 'getPro...
  type CreateProjectMemberBody (line 38) | type CreateProjectMemberBody = ZodiosBodyByAlias<SolidTimeApi, 'createPr...
  type UpdateProjectMemberBody (line 40) | type UpdateProjectMemberBody = ZodiosBodyByAlias<SolidTimeApi, 'updatePr...
  type ProjectMember (line 42) | type ProjectMember = ProjectMemberResponse['data'][0];
  type CreateTaskBody (line 44) | type CreateTaskBody = ZodiosBodyByAlias<SolidTimeApi, 'createTask'>;
  type CreateClientBody (line 46) | type CreateClientBody = ZodiosBodyByAlias<SolidTimeApi, 'createClient'>;
  type UpdateClientBody (line 47) | type UpdateClientBody = ZodiosBodyByAlias<SolidTimeApi, 'updateClient'>;
  type TagIndexResponse (line 49) | type TagIndexResponse = ZodiosResponseByAlias<SolidTimeApi, 'getTags'>;
  type Tag (line 50) | type Tag = TagIndexResponse['data'][0];
  type TaskIndexResponse (line 52) | type TaskIndexResponse = ZodiosResponseByAlias<SolidTimeApi, 'getTasks'>;
  type Task (line 53) | type Task = TaskIndexResponse['data'][0];
  type UpdateTaskBody (line 55) | type UpdateTaskBody = ZodiosBodyByAlias<SolidTimeApi, 'updateTask'>;
  type ClientIndexResponse (line 57) | type ClientIndexResponse = ZodiosResponseByAlias<SolidTimeApi, 'getClien...
  type Client (line 58) | type Client = ClientIndexResponse['data'][0];
  type MemberIndexResponse (line 60) | type MemberIndexResponse = ZodiosResponseByAlias<SolidTimeApi, 'getMembe...
  type Member (line 61) | type Member = MemberIndexResponse['data'][0];
  type UpdateMemberBody (line 63) | type UpdateMemberBody = ZodiosBodyByAlias<SolidTimeApi, 'updateMember'>;
  type InviteMemberBody (line 65) | type InviteMemberBody = ZodiosBodyByAlias<SolidTimeApi, 'invite'>;
  type MemberRole (line 66) | type MemberRole = InviteMemberBody['role'];
  type CreateTagBody (line 68) | type CreateTagBody = ZodiosBodyByAlias<SolidTimeApi, 'createTag'>;
  type UpdateTagBody (line 69) | type UpdateTagBody = ZodiosBodyByAlias<SolidTimeApi, 'updateTag'>;
  type ImportType (line 71) | type ImportType = ZodiosResponseByAlias<SolidTimeApi, 'getImporters'>['d...
  type ImportReport (line 72) | type ImportReport = ZodiosResponseByAlias<SolidTimeApi, 'importData'>;
  type ReportingResponse (line 74) | type ReportingResponse = ZodiosResponseByAlias<SolidTimeApi, 'getAggrega...
  type AggregatedTimeEntries (line 76) | type AggregatedTimeEntries = ReportingResponse['data'];
  type GroupedDataEntries (line 77) | type GroupedDataEntries = ReportingResponse['data']['grouped_data'];
  type TimeEntriesQueryParams (line 79) | type TimeEntriesQueryParams = ZodiosQueryParamsByAlias<SolidTimeApi, 'ge...
  type AggregatedTimeEntriesQueryParams (line 81) | type AggregatedTimeEntriesQueryParams = ZodiosQueryParamsByAlias<
  type OrganizationResponse (line 91) | type OrganizationResponse = ZodiosResponseByAlias<SolidTimeApi, 'getOrga...
  type Organization (line 93) | type Organization = ZodiosResponseByAlias<SolidTimeApi, 'getOrganization...
  type UpdateOrganizationBody (line 95) | type UpdateOrganizationBody = ZodiosBodyByAlias<SolidTimeApi, 'updateOrg...
  type MyMemberships (line 97) | type MyMemberships = ZodiosResponseByAlias<SolidTimeApi, 'getMyMembershi...
  type MyMembership (line 99) | type MyMembership = MyMemberships[0];
  type OrganizationExportResponse (line 101) | type OrganizationExportResponse = ZodiosResponseByAlias<SolidTimeApi, 'e...
  type ReportIndexResponse (line 103) | type ReportIndexResponse = ZodiosResponseByAlias<SolidTimeApi, 'getRepor...
  type CreateReportBody (line 105) | type CreateReportBody = ZodiosBodyByAlias<SolidTimeApi, 'createReport'>;
  type UpdateReportBody (line 106) | type UpdateReportBody = ZodiosBodyByAlias<SolidTimeApi, 'updateReport'>;
  type CreateReportBodyProperties (line 107) | type CreateReportBodyProperties = CreateReportBody['properties'];
  type Report (line 108) | type Report = ReportIndexResponse['data'][0];
  type ApiTokenIndexResponse (line 110) | type ApiTokenIndexResponse = ZodiosResponseByAlias<SolidTimeApi, 'getApi...
  type CreateApiTokenBody (line 112) | type CreateApiTokenBody = ZodiosBodyByAlias<SolidTimeApi, 'createApiToke...
  type ApiToken (line 113) | type ApiToken = ApiTokenIndexResponse['data'][0];
  type DetailedInvoiceResponse (line 115) | type DetailedInvoiceResponse = ZodiosResponseByAlias<SolidTimeApi, 'getI...
  type InvoiceIndexEntry (line 117) | type InvoiceIndexEntry = ZodiosResponseByAlias<SolidTimeApi, 'getInvoice...
  type UpdateInvoiceSettings (line 119) | type UpdateInvoiceSettings = ZodiosBodyByAlias<SolidTimeApi, 'updateInvo...
  type CreateInvoiceBody (line 121) | type CreateInvoiceBody = ZodiosBodyByAlias<SolidTimeApi, 'createInvoice'>;
  type UpdateInvoiceBody (line 123) | type UpdateInvoiceBody = ZodiosBodyByAlias<SolidTimeApi, 'updateInvoice'>;

FILE: resources/js/packages/api/src/openapi.json.client.ts
  function createApiClient (line 4625) | function createApiClient(baseUrl: string, options?: ZodiosOptions) {

FILE: resources/js/packages/ui/src/Buttons/index.ts
  type ButtonVariants (line 35) | type ButtonVariants = VariantProps<typeof buttonVariants>;

FILE: resources/js/packages/ui/src/CommandPalette/CommandPaletteTypes.ts
  type CommandPaletteCommand (line 4) | interface CommandPaletteCommand {
  type CommandPaletteGroup (line 13) | interface CommandPaletteGroup {
  type EntitySearchResult (line 19) | interface EntitySearchResult extends CommandPaletteCommand {

FILE: resources/js/packages/ui/src/FullCalendar/calendarSettings.ts
  type CalendarSettings (line 1) | interface CalendarSettings {

FILE: resources/js/packages/ui/src/FullCalendar/idleStatusPlugin.ts
  type WindowActivityInPeriod (line 4) | interface WindowActivityInPeriod {
  type ActivityPeriod (line 11) | interface ActivityPeriod {
  type ActivityStatusPluginOptions (line 18) | interface ActivityStatusPluginOptions {
  function getOrCreateTooltip (line 29) | function getOrCreateTooltip(): HTMLElement {
  function showTooltip (line 48) | function showTooltip(box: HTMLElement, tooltip: HTMLElement, content: st...
  function hideTooltip (line 81) | function hideTooltip(tooltip: HTMLElement) {
  function formatDuration (line 95) | function formatDuration(durationMinutes: number): string {
  function createTooltipContent (line 104) | function createTooltipContent(
  function renderActivityStatusBoxes (line 198) | function renderActivityStatusBoxes(
  function getSlotDuration (line 311) | function getSlotDuration(calendarEl: HTMLElement): number {
  function calculateBoxPosition (line 336) | function calculateBoxPosition(
  function cleanupActivityStatusPlugin (line 368) | function cleanupActivityStatusPlugin() {

FILE: resources/js/packages/ui/src/FullCalendar/useVisualSnap.ts
  type VisualSnapOptions (line 4) | interface VisualSnapOptions {
  function useVisualSnap (line 11) | function useVisualSnap({

FILE: resources/js/packages/ui/src/field/index.ts
  type FieldVariants (line 28) | type FieldVariants = VariantProps<typeof fieldVariants>;

FILE: resources/js/packages/ui/src/index.ts
  type Window (line 2) | interface Window {

FILE: resources/js/packages/ui/src/utils/cn.ts
  function cn (line 4) | function cn(...inputs: ClassValue[]) {

FILE: resources/js/packages/ui/src/utils/color.ts
  function getRandomColor (line 25) | function getRandomColor() {
  function getRandomColorWithSeed (line 29) | function getRandomColorWithSeed(seed: string) {

FILE: resources/js/packages/ui/src/utils/money.ts
  type CurrencyFormat (line 3) | type CurrencyFormat =
  function formatMoney (line 11) | function formatMoney(
  function formatCents (line 36) | function formatCents(
  function getOrganizationCurrencySymbol (line 46) | function getOrganizationCurrencySymbol(currency: string) {

FILE: resources/js/packages/ui/src/utils/number.ts
  type NumberFormat (line 1) | type NumberFormat =
  function formatNumber (line 14) | function formatNumber(value: number, format?: string): string {

FILE: resources/js/packages/ui/src/utils/random.ts
  class Prando (line 6) | class Prando {
    method constructor (line 21) | constructor(seed?: number | string) {
    method next (line 47) | public next(min = 0, pseudoMax = 1): number {
    method nextInt (line 59) | public nextInt(min = 10, max = 100): number {
    method nextString (line 75) | public nextString(
    method nextChar (line 92) | public nextChar(
    method nextArrayItem (line 109) | public nextArrayItem<T>(array: T[]): T {
    method nextBoolean (line 118) | public nextBoolean(): boolean {
    method skip (line 130) | public skip(iterations = 1): void {
    method reset (line 149) | public reset(): void {
    method recalculate (line 156) | private recalculate(): void {
    method xorshift (line 160) | private xorshift(value: number): number {
    method map (line 169) | private map(
    method hashCode (line 179) | private hashCode(str: string): number {
    method getSafeSeed (line 192) | private getSafeSeed(seed: number): number {

FILE: resources/js/packages/ui/src/utils/select.ts
  function useSelectEvents (line 4) | function useSelectEvents<Type>(

FILE: resources/js/packages/ui/src/utils/settings.ts
  function getWeekStart (line 1) | function getWeekStart() {
  function getUserTimezone (line 11) | function getUserTimezone() {

FILE: resources/js/packages/ui/src/utils/time.ts
  type DateFormat (line 16) | type DateFormat =
  type WeekStartDay (line 25) | type WeekStartDay = 0 | 1 | 2 | 3 | 4 | 5 | 6;
  type TimeFormat (line 36) | type TimeFormat = '12-hours' | '24-hours';
  type IntervalFormat (line 37) | type IntervalFormat =
  type TimeInputUnit (line 42) | type TimeInputUnit = 'minutes' | 'hours';
  function getDayJsInstance (line 53) | function getDayJsInstance() {
  function formatHumanReadableDuration (line 73) | function formatHumanReadableDuration(
  function formatDuration (line 97) | function formatDuration(duration: number): string {
  function calculateDifference (line 105) | function calculateDifference(start: string, end: string | null) {
  function formatTime (line 117) | function formatTime(date: string, timeFormat: TimeFormat = '24-hours') {
  function getLocalizedDayJs (line 122) | function getLocalizedDayJs(timestamp?: string | null) {
  function getLocalizedDateFromTimestamp (line 126) | function getLocalizedDateFromTimestamp(timestamp: string) {
  function formatDate (line 134) | function formatDate(date: string, format: DateFormat = 'point-separated-...
  function formatDateLocalized (line 145) | function formatDateLocalized(
  function formatDateTimeLocalized (line 152) | function formatDateTimeLocalized(
  function formatWeek (line 161) | function formatWeek(date: string | null): string {
  function formatHumanReadableDate (line 169) | function formatHumanReadableDate(date: string) {
  function formatWeekday (line 195) | function formatWeekday(date: string) {
  function formatStartEnd (line 199) | function formatStartEnd(
  function parseTimeInput (line 211) | function parseTimeInput(

FILE: resources/js/types/dom.d.ts
  type HtmlButtonType (line 1) | type HtmlButtonType = 'button' | 'submit' | 'reset';

FILE: resources/js/types/dom.ts
  type HtmlButtonType (line 1) | type HtmlButtonType = 'button' | 'submit' | 'reset';

FILE: resources/js/types/global.d.ts
  type Window (line 8) | interface Window {
  type ComponentCustomProperties (line 20) | interface ComponentCustomProperties {
  type PageProps (line 26) | interface PageProps extends InertiaPageProps, AppPageProps {}

FILE: resources/js/types/inertia.d.ts
  type Props (line 4) | interface Props {

FILE: resources/js/types/jetstream.ts
  type Permissions (line 3) | interface Permissions {
  type Session (line 11) | interface Session {
  type Membership (line 23) | interface Membership {
  type Role (line 27) | interface Role {
  type JetstreamUser (line 33) | type JetstreamUser = User & {
  type Token (line 36) | interface Token {

FILE: resources/js/types/models.d.ts
  type Client (line 1) | interface Client {
  type Membership (line 9) | interface Membership {
  type Organization (line 17) | interface Organization {
  type OrganizationInvitation (line 29) | interface OrganizationInvitation {
  type Project (line 39) | interface Project {
  type Task (line 51) | interface Task {
  type OrganizationWithMembership (line 61) | type OrganizationWithMembership = Organization & {
  type User (line 64) | interface User {

FILE: resources/js/types/models.ts
  type Client (line 1) | interface Client {
  type Membership (line 12) | interface Membership {
  type Organization (line 22) | interface Organization {
  type OrganizationInvitation (line 37) | interface OrganizationInvitation {
  type Project (line 50) | interface Project {
  type Task (line 65) | interface Task {
  type OrganizationWithMembership (line 78) | type OrganizationWithMembership = Organization & { membership: Membershi...
  type User (line 80) | interface User {

FILE: resources/js/types/projects.d.ts
  type BillableKey (line 1) | type BillableKey = 'non-billable' | 'default-rate' | 'custom-rate';

FILE: resources/js/types/reporting.ts
  type ExportFormat (line 1) | type ExportFormat = 'xlsx' | 'csv' | 'ods' | 'pdf';

FILE: resources/js/types/time-entries.d.ts
  type TimeEntriesGroupedByType (line 3) | type TimeEntriesGroupedByType = TimeEntry & { timeEntries: TimeEntry[] };

FILE: resources/js/utils/billing.ts
  function isBillingActivated (line 4) | function isBillingActivated() {
  function isInvoicingActivated (line 12) | function isInvoicingActivated() {
  function isInTrial (line 20) | function isInTrial() {
  function daysLeftInTrial (line 30) | function daysLeftInTrial() {
  function isBlocked (line 42) | function isBlocked() {
  function isFreePlan (line 52) | function isFreePlan() {
  function hasActiveSubscription (line 56) | function hasActiveSubscription() {
  function isAllowedToPerformPremiumAction (line 66) | function isAllowedToPerformPremiumAction() {

FILE: resources/js/utils/commandPaletteCommands.ts
  type CommandGroup (line 29) | type CommandGroup =
  type Command (line 38) | interface Command {
  constant GROUP_PRIORITIES (line 51) | const GROUP_PRIORITIES: Record<CommandGroup, number> = {
  function createNavigationCommands (line 61) | function createNavigationCommands(
  function createTimerCommands (line 229) | function createTimerCommands(
  function createActiveTimerCommands (line 284) | function createActiveTimerCommands(
  function createThemeCommands (line 354) | function createThemeCommands(
  function createCreateCommands (line 388) | function createCreateCommands(
  function createOrganizationCommands (line 458) | function createOrganizationCommands(
  function scoreEntity (line 478) | function scoreEntity(name: string, query: string, baseScore: number): nu...

FILE: resources/js/utils/feedback.ts
  function openFeedback (line 1) | function openFeedback(): void {

FILE: resources/js/utils/fetchAllPages.ts
  function fetchAllPages (line 6) | async function fetchAllPages<T>(

FILE: resources/js/utils/format.ts
  function capitalizeFirstLetter (line 1) | function capitalizeFirstLetter(string: string) {

FILE: resources/js/utils/init.ts
  function initializeStores (line 3) | function initializeStores() {

FILE: resources/js/utils/money.ts
  function getOrganizationCurrencyString (line 13) | function getOrganizationCurrencyString() {

FILE: resources/js/utils/notification.ts
  type NotificationType (line 7) | type NotificationType = 'success' | 'error';
  function addNotification (line 21) | function addNotification(type: NotificationType, title: string, message?...
  function removeNotification (line 30) | function removeNotification(uuid: string) {
  function handleApiRequestNotifications (line 37) | async function handleApiRequestNotifications<T>(

FILE: resources/js/utils/permissions.ts
  function currentUserHasPermission (line 9) | function currentUserHasPermission(permission: string) {
  function canUpdateOrganization (line 16) | function canUpdateOrganization() {
  function canViewProjects (line 20) | function canViewProjects() {
  function canCreateProjects (line 24) | function canCreateProjects() {
  function canUpdateProjects (line 28) | function canUpdateProjects() {
  function canDeleteProjects (line 32) | function canDeleteProjects() {
  function canViewProjectMembers (line 36) | function canViewProjectMembers() {
  function canCreateTasks (line 40) | function canCreateTasks() {
  function canUpdateTasks (line 44) | function canUpdateTasks() {
  function canDeleteTasks (line 48) | function canDeleteTasks() {
  function canCreateClients (line 52) | function canCreateClients() {
  function canUpdateClients (line 56) | function canUpdateClients() {
  function canDeleteClients (line 60) | function canDeleteClients() {
  function canViewClients (line 64) | function canViewClients() {
  function canViewMembers (line 68) | function canViewMembers() {
  function canUpdateMembers (line 72) | function canUpdateMembers() {
  function canDeleteMembers (line 76) | function canDeleteMembers() {
  function canMergeMembers (line 80) | function canMergeMembers() {
  function canMakeMembersPlaceholders (line 84) | function canMakeMembersPlaceholders() {
  function canInvitePlaceholderMembers (line 88) | function canInvitePlaceholderMembers() {
  function canCreateInvitations (line 92) | function canCreateInvitations() {
  function canViewTags (line 96) | function canViewTags() {
  function canCreateTags (line 100) | function canCreateTags() {
  function canUpdateTags (line 104) | function canUpdateTags() {
  function canDeleteTags (line 108) | function canDeleteTags() {
  function canManageBilling (line 112) | function canManageBilling() {
  function canViewReport (line 116) | function canViewReport() {
  function canUpdateReport (line 119) | function canUpdateReport() {
  function canDeleteReport (line 122) | function canDeleteReport() {
  function canViewAllTimeEntries (line 126) | function canViewAllTimeEntries() {
  function canViewInvoices (line 129) | function canViewInvoices() {
  function canCreateReports (line 132) | function canCreateReports() {

FILE: resources/js/utils/prefetch.ts
  function prefetchDashboard (line 85) | function prefetchDashboard(queryClient: QueryClient) {
  function prefetchProjects (line 156) | function prefetchProjects(queryClient: QueryClient) {
  function prefetchTasks (line 167) | function prefetchTasks(queryClient: QueryClient) {
  function prefetchTags (line 178) | function prefetchTags(queryClient: QueryClient) {
  function prefetchClients (line 189) | function prefetchClients(queryClient: QueryClient) {
  function prefetchMembers (line 200) | function prefetchMembers(queryClient: QueryClient) {
  function prefetchReports (line 211) | function prefetchReports(queryClient: QueryClient) {
  function prefetchTimeEntries (line 222) | function prefetchTimeEntries(queryClient: QueryClient) {
  function prefetchCalendarTimeEntries (line 244) | function prefetchCalendarTimeEntries(queryClient: QueryClient) {
  function prefetchProjectMembers (line 260) | function prefetchProjectMembers(queryClient: QueryClient, projectId: str...
  function findPrefetcher (line 277) | function findPrefetcher(url: string): ((queryClient: QueryClient) => voi...
  function setupPrefetching (line 304) | function setupPrefetching(queryClient: QueryClient) {

FILE: resources/js/utils/roles.ts
  function filterRoles (line 3) | function filterRoles(roles: Role[]) {

FILE: resources/js/utils/session.ts
  function fetchToken (line 3) | async function fetchToken() {
  function isTokenValid (line 13) | function isTokenValid() {

FILE: resources/js/utils/theme.ts
  type themeOption (line 4) | type themeOption = 'system' | 'light' | 'dark';
  function useTheme (line 18) | function useTheme() {

FILE: resources/js/utils/useAggregatedTimeEntriesQuery.ts
  function useAggregatedTimeEntriesQuery (line 10) | function useAggregatedTimeEntriesQuery(

FILE: resources/js/utils/useClients.ts
  function createClient (line 12) | async function createClient(clientBody: CreateClientBody): Promise<Clien...
  function updateClient (line 30) | async function updateClient(clientId: string, clientBody: UpdateClientBo...
  function deleteClient (line 48) | async function deleteClient(clientId: string) {

FILE: resources/js/utils/useClientsQuery.ts
  function fetchAllClients (line 8) | async function fetchAllClients(organizationId: string): Promise<Client[]> {
  function useClientsQuery (line 17) | function useClientsQuery() {

FILE: resources/js/utils/useCommandPalette.ts
  constant GROUP_CONFIG (line 75) | const GROUP_CONFIG: { id: CommandGroupType; heading: string }[] = [
  constant ENTITY_BADGE_CLASSES (line 85) | const ENTITY_BADGE_CLASSES: Record<string, string> = {
  constant ENTITY_ICONS (line 94) | const ENTITY_ICONS: Record<string, typeof FolderIcon> = {
  function useCommandPalette (line 102) | function useCommandPalette() {

FILE: resources/js/utils/useCssVariable.ts
  function useCssVariable (line 3) | function useCssVariable(variableName: string) {

FILE: resources/js/utils/useCurrentTimeEntry.ts
  function $reset (line 41) | function $reset() {
  function startLiveTimer (line 48) | function startLiveTimer() {
  function stopLiveTimer (line 56) | function stopLiveTimer() {
  function fetchCurrentTimeEntry (line 62) | async function fetchCurrentTimeEntry() {
  function startTimer (line 102) | async function startTimer() {
  function stopTimer (line 136) | async function stopTimer() {
  function updateTimer (line 164) | async function updateTimer() {
  function setActiveState (line 216) | async function setActiveState(newState: boolean) {

FILE: resources/js/utils/useInvitations.ts
  function fetchAllInvitations (line 9) | async function fetchAllInvitations(organizationId: string): Promise<Invi...
  function fetchInvitations (line 22) | async function fetchInvitations() {
  function createInvitation (line 36) | async function createInvitation(inviteBody: CreateInvitationBody): Promi...

FILE: resources/js/utils/useMembers.ts
  type MemberBillableKey (line 8) | type MemberBillableKey = 'default-rate' | 'custom-rate';
  function removeMember (line 14) | async function removeMember(membershipId: string) {
  function updateMember (line 32) | async function updateMember(memberId: string, memberBody: UpdateMemberBo...

FILE: resources/js/utils/useMembersQuery.ts
  function fetchAllMembers (line 8) | async function fetchAllMembers(organizationId: string): Promise<Member[]> {
  function useMembersQuery (line 17) | function useMembersQuery() {

FILE: resources/js/utils/useOrganization.ts
  function switchOrganization (line 14) | function switchOrganization(organizationId: string) {
  function fetchOrganization (line 37) | async function fetchOrganization() {
  function updateOrganization (line 53) | async function updateOrganization(organizationBody: UpdateOrganizationBo...

FILE: resources/js/utils/useOrganizationQuery.ts
  function useOrganizationQuery (line 5) | function useOrganizationQuery(organizationId: string) {

FILE: resources/js/utils/useProjectMembers.ts
  function createProjectMember (line 12) | async function createProjectMember(
  function updateProjectMember (line 35) | async function updateProjectMember(
  function deleteProjectMember (line 60) | async function deleteProjectMember(projectId: string, projectMemberId: s...

FILE: resources/js/utils/useProjectMembersQuery.ts
  function fetchAllProjectMembers (line 8) | async function fetchAllProjectMembers(
  function useProjectMembersQuery (line 20) | function useProjectMembersQuery(projectId: Ref<string | null> | string) {

FILE: resources/js/utils/useProjects.ts
  function createProject (line 12) | async function createProject(projectBody: CreateProjectBody) {
  function deleteProject (line 32) | async function deleteProject(projectId: string) {
  function updateProject (line 50) | async function updateProject(projectId: string, updateProjectBody: Updat...

FILE: resources/js/utils/useProjectsQuery.ts
  function fetchAllProjects (line 8) | async function fetchAllProjects(organizationId: string): Promise<Project...
  function useProjectsQuery (line 17) | function useProjectsQuery() {

FILE: resources/js/utils/useReporting.ts
  type GroupingOption (line 13) | type GroupingOption =
  function getNameForReportingRowEntry (line 40) | function getNameForReportingRowEntry(key: string | null, type: string | ...

FILE: resources/js/utils/useReportsQuery.ts
  function fetchAllReports (line 5) | async function fetchAllReports(organizationId: string): Promise<Report[]> {

FILE: resources/js/utils/useTags.ts
  function deleteTag (line 12) | async function deleteTag(tagId: string) {
  function createTag (line 30) | async function createTag(name: string): Promise<Tag | undefined> {

FILE: resources/js/utils/useTagsQuery.ts
  function fetchAllTags (line 8) | async function fetchAllTags(organizationId: string): Promise<Tag[]> {
  function useTagsQuery (line 17) | function useTagsQuery() {

FILE: resources/js/utils/useTasks.ts
  function updateTask (line 12) | async function updateTask(taskId: string, taskBody: UpdateTaskBody) {
  function createTask (line 30) | async function createTask(task: CreateTaskBody) {
  function deleteTask (line 47) | async function deleteTask(taskId: string) {

FILE: resources/js/utils/useTasksQuery.ts
  function fetchAllTasks (line 8) | async function fetchAllTasks(organizationId: string): Promise<Task[]> {
  function useTasksQuery (line 17) | function useTasksQuery() {

FILE: resources/js/utils/useTimeEntriesCalendarQuery.ts
  function getExpandedCalendarDateRange (line 22) | function getExpandedCalendarDateRange(
  function getInitialWeekRange (line 49) | function getInitialWeekRange(): { start: Date; end: Date } {
  function createCalendarQueryKey (line 69) | function createCalendarQueryKey(
  function fetchAllCalendarEntries (line 84) | async function fetchAllCalendarEntries(
  function useTimeEntriesCalendarQuery (line 117) | function useTimeEntriesCalendarQuery(

FILE: resources/js/utils/useTimeEntriesInfiniteQuery.ts
  function useTimeEntriesInfiniteQuery (line 7) | function useTimeEntriesInfiniteQuery() {

FILE: resources/js/utils/useTimeEntriesMutations.ts
  function useTimeEntriesMutations (line 11) | function useTimeEntriesMutations() {

FILE: resources/js/utils/useTimeEntriesReportQuery.ts
  function useTimeEntriesReportQuery (line 6) | function useTimeEntriesReportQuery(

FILE: resources/js/utils/useUser.ts
  function getCurrentUserId (line 9) | function getCurrentUserId() {
  function getCurrentUser (line 13) | function getCurrentUser() {
  function getCurrentOrganizationId (line 17) | function getCurrentOrganizationId() {
  function getCurrentMembershipId (line 21) | function getCurrentMembershipId() {
  function getCurrentRole (line 26) | function getCurrentRole() {

FILE: resources/js/ziggy.d.ts
  type RouteList (line 3) | interface RouteList {

FILE: tests/CreatesApplication.php
  type CreatesApplication (line 10) | trait CreatesApplication
    method createApplication (line 15) | public function createApplication(): Application

FILE: tests/Feature/AuthenticationTest.php
  class AuthenticationTest (line 12) | class AuthenticationTest extends TestCase
    method test_login_screen_can_be_rendered (line 16) | public function test_login_screen_can_be_rendered(): void
    method test_users_can_authenticate_using_the_login_screen (line 23) | public function test_users_can_authenticate_using_the_login_screen(): ...
    method test_users_can_not_authenticate_with_invalid_password (line 36) | public function test_users_can_not_authenticate_with_invalid_password(...

FILE: tests/Feature/BrowserSessionsTest.php
  class BrowserSessionsTest (line 11) | class BrowserSessionsTest extends TestCase
    method test_other_browser_sessions_can_be_logged_out (line 15) | public function test_other_browser_sessions_can_be_logged_out(): void

FILE: tests/Feature/CreateOrganizationTest.php
  class CreateOrganizationTest (line 16) | class CreateOrganizationTest extends TestCase
    method test_organizations_can_be_created (line 20) | public function test_organizations_can_be_created(): void

FILE: tests/Feature/DeleteAccountTest.php
  class DeleteAccountTest (line 14) | class DeleteAccountTest extends TestCase
    method test_user_accounts_can_be_deleted (line 18) | public function test_user_accounts_can_be_deleted(): void
    method test_correct_password_must_be_provided_before_account_can_be_deleted (line 34) | public function test_correct_password_must_be_provided_before_account_...
    method test_user_account_can_not_be_deleted_if_attached_to_a_organization_with_multiple_users (line 49) | public function test_user_account_can_not_be_deleted_if_attached_to_a_...

FILE: tests/Feature/DeleteOrganizationTest.php
  class DeleteOrganizationTest (line 14) | class DeleteOrganizationTest extends TestCase
    method test_organizations_can_be_deleted_and_users_of_the_organization_that_have_no_organization_get_a_new_one (line 18) | public function test_organizations_can_be_deleted_and_users_of_the_org...
    method test_personal_organizations_can_be_deleted_but_user_gets_an_new_one_if_this_is_the_only_one_left (line 43) | public function test_personal_organizations_can_be_deleted_but_user_ge...
    method test_organization_can_not_be_deleted_if_user_is_not_owner (line 61) | public function test_organization_can_not_be_deleted_if_user_is_not_ow...

FILE: tests/Feature/EmailVerificationTest.php
  class EmailVerificationTest (line 16) | class EmailVerificationTest extends TestCase
    method test_email_verification_screen_can_be_rendered (line 20) | public function test_email_verification_screen_can_be_rendered(): void
    method test_email_can_be_verified (line 33) | public function test_email_can_be_verified(): void
    method test_email_can_not_verified_with_invalid_hash (line 59) | public function test_email_can_not_verified_with_invalid_hash(): void

FILE: tests/Feature/InviteTeamMemberTest.php
  class InviteTeamMemberTest (line 16) | class InviteTeamMemberTest extends TestCase
    method test_team_members_can_no_longer_be_invited_to_team_over_jetstream (line 20) | public function test_team_members_can_no_longer_be_invited_to_team_ove...
    method test_team_member_invitations_can_no_longer_be_cancelled_over_jetstream (line 38) | public function test_team_member_invitations_can_no_longer_be_cancelle...
    method test_team_member_invitations_can_be_accepted (line 58) | public function test_team_member_invitations_can_be_accepted(): void
    method test_team_member_invitations_of_placeholder_can_be_accepted_and_migrates_date_to_real_user (line 85) | public function test_team_member_invitations_of_placeholder_can_be_acc...
    method test_team_member_accept_fails_if_user_with_that_email_does_not_exist (line 123) | public function test_team_member_accept_fails_if_user_with_that_email_...

FILE: tests/Feature/LeaveTeamTest.php
  class LeaveTeamTest (line 11) | class LeaveTeamTest extends TestCase
    method test_users_can_no_longer_leave_team_over_jetstream (line 15) | public function test_users_can_no_longer_leave_team_over_jetstream(): ...

FILE: tests/Feature/PasswordConfirmationTest.php
  class PasswordConfirmationTest (line 11) | class PasswordConfirmationTest extends TestCase
    method test_confirm_password_screen_can_be_rendered (line 15) | public function test_confirm_password_screen_can_be_rendered(): void
    method test_password_can_be_confirmed (line 24) | public function test_password_can_be_confirmed(): void
    method test_password_is_not_confirmed_with_invalid_password (line 36) | public function test_password_is_not_confirmed_with_invalid_password()...

FILE: tests/Feature/PasswordResetTest.php
  class PasswordResetTest (line 14) | class PasswordResetTest extends TestCase
    method test_reset_password_link_screen_can_be_rendered (line 18) | public function test_reset_password_link_screen_can_be_rendered(): void
    method test_reset_password_link_can_be_requested (line 29) | public function test_reset_password_link_can_be_requested(): void
    method test_reset_password_screen_can_be_rendered (line 46) | public function test_reset_password_screen_can_be_rendered(): void
    method test_password_can_be_reset_with_valid_token (line 69) | public function test_password_can_be_reset_with_valid_token(): void

FILE: tests/Feature/ProfileInformationTest.php
  class ProfileInformationTest (line 13) | class ProfileInformationTest extends TestCase
    method test_show_profile_information_succeeds (line 17) | public function test_show_profile_information_succeeds(): void
    method test_profile_information_can_be_updated (line 30) | public function test_profile_information_can_be_updated(): void

FILE: tests/Feature/RegistrationTest.php
  class RegistrationTest (line 22) | class RegistrationTest extends TestCase
    method test_registration_screen_can_be_rendered (line 26) | public function test_registration_screen_can_be_rendered(): void
    method test_new_users_can_register (line 37) | public function test_new_users_can_register(): void
    method test_user_registration_fails_if_registration_is_deactivated (line 67) | public function test_user_registration_fails_if_registration_is_deacti...
    method test_new_user_can_not_register_with_likely_invalid_domain (line 92) | public function test_new_user_can_not_register_with_likely_invalid_dom...
    method test_new_user_can_register_with_uppercase_email (line 107) | public function test_new_user_can_register_with_uppercase_email(): void
    method test_new_users_can_consent_to_newsletter_during_registration (line 122) | public function test_new_users_can_consent_to_newsletter_during_regist...
    method test_new_users_can_register_and_frontend_can_send_timezone_for_user (line 149) | public function test_new_users_can_register_and_frontend_can_send_time...
    method test_new_users_can_register_and_uses_ip_lookup_service_to_get_information_about_currency_and_start_of_week (line 168) | public function test_new_users_can_register_and_uses_ip_lookup_service...
    method test_new_users_can_register_and_uses_ip_lookup_service_to_get_information_about_timezone_if_client_did_not_send_one (line 199) | public function test_new_users_can_register_and_uses_ip_lookup_service...
    method test_new_users_can_register_and_uses_ip_lookup_service_to_get_information_about_timezone_if_client_sends_invalid_one (line 230) | public function test_new_users_can_register_and_uses_ip_lookup_service...
    method test_new_users_can_register_and_legacy_timezone_from_client_is_mapped_to_new_timezone (line 261) | public function test_new_users_can_register_and_legacy_timezone_from_c...
    method test_new_users_can_register_and_ignores_invalid_timezones_from_frontend (line 292) | public function test_new_users_can_register_and_ignores_invalid_timezo...
    method test_new_users_can_not_register_if_user_with_email_already_exists (line 309) | public function test_new_users_can_not_register_if_user_with_email_alr...
    method test_new_users_can_register_if_placeholder_user_with_email_already_exists (line 329) | public function test_new_users_can_register_if_placeholder_user_with_e...

FILE: tests/Feature/RemoveTeamMemberTest.php
  class RemoveTeamMemberTest (line 11) | class RemoveTeamMemberTest extends TestCase
    method test_team_members_can_no_longer_be_removed_from_teams_over_jetstream_endpoints (line 15) | public function test_team_members_can_no_longer_be_removed_from_teams_...

FILE: tests/Feature/TwoFactorAuthenticationSettingsTest.php
  class TwoFactorAuthenticationSettingsTest (line 12) | class TwoFactorAuthenticationSettingsTest extends TestCase
    method test_two_factor_authentication_can_be_enabled (line 16) | public function test_two_factor_authentication_can_be_enabled(): void
    method test_recovery_codes_can_be_regenerated (line 32) | public function test_recovery_codes_can_be_regenerated(): void
    method test_two_factor_authentication_can_be_disabled (line 53) | public function test_two_factor_authentication_can_be_disabled(): void

FILE: tests/Feature/UpdatePasswordTest.php
  class UpdatePasswordTest (line 12) | class UpdatePasswordTest extends TestCase
    method test_password_can_be_updated (line 16) | public function test_password_can_be_updated(): void
    method test_current_password_must_be_correct (line 29) | public function test_current_password_must_be_correct(): void
    method test_new_passwords_must_match (line 44) | public function test_new_passwords_must_match(): void

FILE: tests/Feature/UpdateTeamMemberRoleTest.php
  class UpdateTeamMemberRoleTest (line 12) | class UpdateTeamMemberRoleTest extends TestCase
    method test_team_member_roles_can_no_longer_be_updated_over_jetstream (line 16) | public function test_team_member_roles_can_no_longer_be_updated_over_j...

FILE: tests/Feature/UpdateTeamTest.php
  class UpdateTeamTest (line 11) | class UpdateTeamTest extends TestCase
    method test_team_update_page_shows_not_found_if_id_is_not_uuid (line 15) | public function test_team_update_page_shows_not_found_if_id_is_not_uui...
    method test_team_names_can_be_updated (line 28) | public function test_team_names_can_be_updated(): void

FILE: tests/TestCase.php
  class TestCase (line 20) | abstract class TestCase extends BaseTestCase
    method setUp (line 26) | protected function setUp(): void
    method mockPrivateStorage (line 39) | protected function mockPrivateStorage(): void
    method mockPublicStorage (line 44) | protected function mockPublicStorage(): void
    method tearDown (line 49) | protected function tearDown(): void
    method assertEqualsIdsOfEloquentCollection (line 56) | protected function assertEqualsIdsOfEloquentCollection(array $ids, Col...
    method travelTo (line 69) | public function travelTo($date, $callback = null): void
    method assertBillableRateServiceIsUnused (line 74) | protected function assertBillableRateServiceIsUnused(): void
    method actAsOrganizationWithSubscription (line 84) | protected function actAsOrganizationWithSubscription(): void
    method actAsOrganizationWithoutSubscriptionAndWithoutTrial (line 94) | protected function actAsOrganizationWithoutSubscriptionAndWithoutTrial...

FILE: tests/TestCaseWithDatabase.php
  class TestCaseWithDatabase (line 16) | abstract class TestCaseWithDatabase extends TestCase
    method createUserWithPermission (line 24) | protected function createUserWithPermission(array $permissions = [], b...
    method createUserWithRole (line 59) | public function createUserWithRole(Role $role, bool $employeesCanSeeBi...
    method enableQueryLog (line 87) | protected function enableQueryLog(): void
    method getQueryLog (line 93) | protected function getQueryLog(): array
    method assertQueryCount (line 102) | protected function assertQueryCount(int $count, string $message = ''):...

FILE: tests/Unit/Console/Commands/Admin/OrganizationDeleteCommandTest.php
  class OrganizationDeleteCommandTest (line 15) | #[CoversClass(OrganizationDeleteCommand::class)]
    method test_it_calls_the_deletion_service_with_the_organization (line 18) | public function test_it_calls_the_deletion_service_with_the_organizati...
    method test_it_fails_if_organization_does_not_exist (line 37) | public function test_it_fails_if_organization_does_not_exist(): void
    method test_it_fails_if_organization_id_is_not_a_valid_uuid (line 50) | public function test_it_fails_if_organization_id_is_not_a_valid_uuid()...

FILE: tests/Unit/Console/Commands/Admin/UserCreateCommandCommandTest.php
  class UserCreateCommandCommandTest (line 15) | #[CoversClass(UserCreateCommand::class)]
    method test_it_creates_user (line 18) | public function test_it_creates_user(): void
    method test_created_user_is_verified_if_option_is_set (line 41) | public function test_created_user_is_verified_if_option_is_set(): void
    method test_it_fails_if_user_with_email_already_exists (line 66) | public function test_it_fails_if_user_with_email_already_exists(): void
    method test_it_asks_for_password_if_option_is_set (line 88) | public function test_it_asks_for_password_if_option_is_set(): void

FILE: tests/Unit/Console/Commands/Admin/UserVerifyCommandTest.php
  class UserVerifyCommandTest (line 14) | #[CoversClass(UserVerifyCommand::class)]
    method test_it_verifies_user_email (line 17) | public function test_it_verifies_user_email(): void
    method test_it_fails_if_user_does_not_exist (line 35) | public function test_it_fails_if_user_does_not_exist(): void
    method test_it_fails_if_user_email_is_already_verified (line 54) | public function test_it_fails_if_user_email_is_already_verified(): void

FILE: tests/Unit/Console/Commands/Auth/AuthSendReminderForExpiringApiTokensCommandTest.php
  class AuthSendReminderForExpiringApiTokensCommandTest (line 19) | #[CoversClass(AuthSendReminderForExpiringApiTokensCommand::class)]
    method test_sends_mail_for_expired_api_tokens_but_ignores_the_one_where_the_mail_was_already_sent_and_ignores_non_api_tokens (line 22) | public function test_sends_mail_for_expired_api_tokens_but_ignores_the...
    method test_sends_mail_for_api_tokens_that_expire_soon_but_ignores_the_one_where_the_mail_was_already_sent_and_ignores_non_api_tokens (line 71) | public function test_sends_mail_for_api_tokens_that_expire_soon_but_ig...

FILE: tests/Unit/Console/Commands/Correction/CorrectionPlaceholderMembersCommandTest.php
  class CorrectionPlaceholderMembersCommandTest (line 17) | #[CoversClass(CorrectionPlaceholderMembersCommand::class)]
    method test_sets_member_role_to_placeholder_if_user_is_placeholder (line 20) | public function test_sets_member_role_to_placeholder_if_user_is_placeh...
    method test_sets_member_role_to_placeholder_if_user_is_placeholder_dry_run (line 43) | public function test_sets_member_role_to_placeholder_if_user_is_placeh...

FILE: tests/Unit/Console/Commands/Report/ReportSetExpiredToPrivateCommandTest.php
  class ReportSetExpiredToPrivateCommandTest (line 14) | #[CoversClass(ReportSetExpiredToPrivateCommand::class)]
    method test_command_sets_expired_reports_to_private (line 17) | public function test_command_sets_expired_reports_to_private(): void
    method test_command_sets_expired_reports_to_private_in_dry_run_mode (line 69) | public function test_command_sets_expired_reports_to_private_in_dry_ru...

FILE: tests/Unit/Console/Commands/SelfHost/SelfHostCheckForUpdateCommandTest.php
  class SelfHostCheckForUpdateCommandTest (line 17) | #[CoversClass(SelfHostCheckForUpdateCommand::class)]
    method test_checks_for_update_and_saves_version_in_cache (line 21) | public function test_checks_for_update_and_saves_version_in_cache(): void
    method test_checks_for_update_fails_gracefully_if_response_has_error_status_code (line 37) | public function test_checks_for_update_fails_gracefully_if_response_ha...
    method test_checks_for_update_fails_gracefully_if_timeout_happens (line 53) | public function test_checks_for_update_fails_gracefully_if_timeout_hap...

FILE: tests/Unit/Console/Commands/SelfHost/SelfHostDatabaseConsistencyCommandTest.php
  class SelfHostDatabaseConsistencyCommandTest (line 20) | #[CoversClass(SelfHostDatabaseConsistency::class)]
    method test_checks_that_task_need_to_be_part_of_project_in_time_entries (line 23) | public function test_checks_that_task_need_to_be_part_of_project_in_ti...
    method test_checks_that_client_id_is_the_client_id_of_the_project (line 41) | public function test_checks_that_client_id_is_the_client_id_of_the_pro...
    method test_checks_that_client_id_is_the_client_id_of_the_project_with_no_client_in_time_entry (line 61) | public function test_checks_that_client_id_is_the_client_id_of_the_pro...
    method test_checks_that_client_id_is_only_null_if_project_is_also_null (line 81) | public function test_checks_that_client_id_is_only_null_if_project_is_...
    method test_checks_that_every_user_needs_to_be_a_member_of_at_least_one_organization (line 100) | public function test_checks_that_every_user_needs_to_be_a_member_of_at...
    method test_checks_that_every_organization_needs_at_least_an_owner (line 114) | public function test_checks_that_every_organization_needs_at_least_an_...
    method test_checks_that_every_member_can_only_have_one_running_time_entry (line 129) | public function test_checks_that_every_member_can_only_have_one_runnin...
    method test_checks_that_users_have_a_current_organization_that_they_are_not_a_member_of (line 145) | public function test_checks_that_users_have_a_current_organization_tha...

FILE: tests/Unit/Console/Commands/SelfHost/SelfHostGenerateKeysCommandTest.php
  class SelfHostGenerateKeysCommandTest (line 13) | #[CoversClass(SelfHostGenerateKeysCommand::class)]
    method test_generates_app_key_and_passport_keys_per_default_in_env_format (line 16) | public function test_generates_app_key_and_passport_keys_per_default_i...
    method test_generates_app_key_and_passport_keys_in_env_format_in_multiline_if_requested (line 31) | public function test_generates_app_key_and_passport_keys_in_env_format...
    method test_generates_app_key_and_passport_keys_in_yaml_format_if_requested (line 46) | public function test_generates_app_key_and_passport_keys_in_yaml_forma...
    method test_generates_app_fail_if_attribute_format_is_invalid (line 61) | public function test_generates_app_fail_if_attribute_format_is_invalid...

FILE: tests/Unit/Console/Commands/SelfHost/SelfHostTelemetryCommandTest.php
  class SelfHostTelemetryCommandTest (line 16) | #[CoversClass(SelfHostTelemetryCommand::class)]
    method test_telemetry_sends_data_to_telemetry_endpoint_of_solidtime_cloud (line 20) | public function test_telemetry_sends_data_to_telemetry_endpoint_of_sol...
    method test_telemetry_sends_fails_gracefully_if_response_has_error_status_code (line 36) | public function test_telemetry_sends_fails_gracefully_if_response_has_...
    method test_telemetry_sends_fails_gracefully_if_timeout_happens (line 52) | public function test_telemetry_sends_fails_gracefully_if_timeout_happe...

FILE: tests/Unit/Console/Commands/TimeEntry/TimeEntrySendStillRunningMailsCommandTest.php
  class TimeEntrySendStillRunningMailsCommandTest (line 17) | #[CoversClass(TimeEntrySendStillRunningMailsCommand::class)]
    method test_sends_mails_for_still_running_time_entries (line 20) | public function test_sends_mails_for_still_running_time_entries(): void
    method test_does_not_send_emails_for_not_running_time_entries (line 48) | public function test_does_not_send_emails_for_not_running_time_entries...
    method test_does_not_send_emails_for_running_time_entries_that_are_short_than_the_threshold (line 70) | public function test_does_not_send_emails_for_running_time_entries_tha...
    method test_does_not_send_emails_for_running_time_entries_that_are_longer_than_the_threshold_but_already_received_the_email (line 92) | public function test_does_not_send_emails_for_running_time_entries_tha...
    method test_dry_run_option_does_not_send_mails_but_outputs_what_would_happen (line 115) | public function test_dry_run_option_does_not_send_mails_but_outputs_wh...
    method test_does_not_send_emails_for_placeholder_users (line 139) | public function test_does_not_send_emails_for_placeholder_users(): void

FILE: tests/Unit/Console/KernelTest.php
  class KernelTest (line 11) | #[CoversClass(Kernel::class)]
    method test_self_host_commands_schedule_time_is_consistent_with_app_key (line 14) | public function test_self_host_commands_schedule_time_is_consistent_wi...
    method test_self_hosting_telemetry_can_be_activated (line 51) | public function test_self_hosting_telemetry_can_be_activated(): void
    method test_self_hosting_telemetry_can_be_deactivated (line 67) | public function test_self_hosting_telemetry_can_be_deactivated(): void
    method test_self_hosting_check_for_update_can_be_activated (line 83) | public function test_self_hosting_check_for_update_can_be_activated():...
    method test_self_hosting_check_for_update_can_be_deactivated (line 99) | public function test_self_hosting_check_for_update_can_be_deactivated(...

FILE: tests/Unit/Database/MigrationTest.php
  class MigrationTest (line 10) | class MigrationTest extends TestCase
    method test_fresh_migration_and_rollback_runs_successfully (line 14) | public function test_fresh_migration_and_rollback_runs_successfully():...

FILE: tests/Unit/Database/SeederTest.php
  class SeederTest (line 11) | class SeederTest extends TestCase
    method test_running_the_seeder_multiple_times_runs_successfully (line 15) | public function test_running_the_seeder_multiple_times_runs_successful...
    method test_fresh_migration_with_seeder_and_rollback_runs_successfully (line 24) | public function test_fresh_migration_with_seeder_and_rollback_runs_suc...
    method setupForSeeder (line 33) | private function setupForSeeder(): void

FILE: tests/Unit/Endpoint/Api/V1/ApiEndpointTestAbstract.php
  class ApiEndpointTestAbstract (line 10) | class ApiEndpointTestAbstract extends TestCaseWithDatabase
    method assertResponseCode (line 12) | protected function assertResponseCode(TestResponse $response, int $sta...

FILE: tests/Unit/Endpoint/Api/V1/ApiTokenEndpointTest.php
  class ApiTokenEndpointTest (line 14) | #[UsesClass(ApiTokenController::class)]
    method test_index_endpoint_returns_list_api_tokens (line 17) | public function test_index_endpoint_returns_list_api_tokens(): void
    method test_index_endpoint_returns_api_tokens_ordered_by_created_at_descending (line 49) | public function test_index_endpoint_returns_api_tokens_ordered_by_crea...
    method test_store_endpoint_creates_new_api_token (line 74) | public function test_store_endpoint_creates_new_api_token(): void
    method test_store_fails_if_personal_access_client_is_not_configured (line 101) | public function test_store_fails_if_personal_access_client_is_not_conf...
    method test_revoke_endpoint_revokes_api_token (line 121) | public function test_revoke_endpoint_revokes_api_token(): void
    method test_revoke_fails_if_token_is_not_personal_access_token (line 140) | public function test_revoke_fails_if_token_is_not_personal_access_toke...
    method test_revoke_fails_if_token_with_id_does_not_exist (line 160) | public function test_revoke_fails_if_token_with_id_does_not_exist(): void
    method test_revoke_fails_if_the_token_does_not_belong_to_the_user (line 173) | public function test_revoke_fails_if_the_token_does_not_belong_to_the_...
    method test_destroy_endpoint_deletes_api_token (line 193) | public function test_destroy_endpoint_deletes_api_token(): void
    method test_destroy_fails_if_token_is_not_personal_access_token (line 209) | public function test_destroy_fails_if_token_is_not_personal_access_tok...
    method test_destroy_fails_if_token_with_id_does_not_exist (line 228) | public function test_destroy_fails_if_token_with_id_does_not_exist(): ...
    method test_destroy_fails_if_the_token_does_not_belong_to_the_user (line 241) | public function test_destroy_fails_if_the_token_does_not_belong_to_the...
    method createPersonalAccessClient (line 260) | private function createPersonalAccessClient(): Client
    method createClient (line 269) | private function createClient(): Client

FILE: tests/Unit/Endpoint/Api/V1/ChartEndpointTest.php
  class ChartEndpointTest (line 11) | class ChartEndpointTest extends EndpointTestAbstract
    method test_weekly_project_overview_endpoint_fails_if_user_has_no_permission_to_view_chart (line 13) | public function test_weekly_project_overview_endpoint_fails_if_user_ha...
    method test_weekly_project_overview_endpoint_returns_chart_data (line 28) | public function test_weekly_project_overview_endpoint_returns_chart_da...
    method test_latest_tasks_endpoint_fails_if_user_has_no_permission_to_view_chart (line 43) | public function test_latest_tasks_endpoint_fails_if_user_has_no_permis...
    method test_latest_tasks_endpoint_returns_chart_data (line 58) | public function test_latest_tasks_endpoint_returns_chart_data(): void
    method test_last_seven_days_endpoint_fails_if_user_has_no_permission_to_view_chart (line 73) | public function test_last_seven_days_endpoint_fails_if_user_has_no_per...
    method test_last_seven_days_endpoint_returns_chart_data (line 88) | public function test_last_seven_days_endpoint_returns_chart_data(): void
    method test_latest_team_activity_endpoint_fails_if_user_has_no_permission_to_view_chart_for_the_whole_orgnaization (line 103) | public function test_latest_team_activity_endpoint_fails_if_user_has_n...
    method test_latest_team_activity_endpoint_returns_chart_data (line 118) | public function test_latest_team_activity_endpoint_returns_chart_data(...
    method test_daily_tracked_hours_endpoint_fails_if_user_has_no_permission_to_view_chart (line 133) | public function test_daily_tracked_hours_endpoint_fails_if_user_has_no...
    method test_daily_tracked_hours_endpoint_returns_chart_data (line 148) | public function test_daily_tracked_hours_endpoint_returns_chart_data()...
    method test_total_weekly_time_endpoint_fails_if_user_has_no_permission_to_view_chart (line 163) | public function test_total_weekly_time_endpoint_fails_if_user_has_no_p...
    method test_total_weekly_time_endpoint_returns_chart_data (line 178) | public function test_total_weekly_time_endpoint_returns_chart_data(): ...
    method test_total_weekly_billable_time_endpoint_fails_if_user_has_no_permission_to_view_chart (line 193) | public function test_total_weekly_billable_time_endpoint_fails_if_user...
    method test_total_weekly_billable_time_endpoint_returns_chart_data (line 208) | public function test_total_
Condensed preview — 1208 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,313K chars).
[
  {
    "path": ".editorconfig",
    "chars": 258,
    "preview": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_size = 4\nindent_style = space\ninsert_final_newline = true\ntrim_"
  },
  {
    "path": ".gitattributes",
    "chars": 186,
    "preview": "* text=auto eol=lf\n\n*.blade.php diff=html\n*.css diff=css\n*.html diff=html\n*.md diff=markdown\n*.php diff=php\n\n/.github ex"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 21,
    "preview": "github: solidtime-io\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/1_bug_report.yml",
    "chars": 1133,
    "preview": "name: Bug Report\ndescription: \"Report a bug\"\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Before crea"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 353,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  - name: 🚀 Feature Request\n    url: https://github.com/solidtime-io/solidtim"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 554,
    "preview": "## What does this PR do?\n\n<!-- Please include a summary of the change and which issue is fixed. Please also include rele"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 1049,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n   "
  },
  {
    "path": ".github/workflows/build-onpremise.yml",
    "chars": 6725,
    "preview": "on:\n  push:\n    branches:\n      - main\n      - develop\n    tags:\n      - '*'\n  pull_request:\n    paths:\n      - '.github"
  },
  {
    "path": ".github/workflows/build-private.yml",
    "chars": 6472,
    "preview": "on:\n  push:\n    branches:\n      - main\n      - develop\n    tags:\n      - '*'\n  pull_request:\n    paths:\n      - '.github"
  },
  {
    "path": ".github/workflows/build-public.yml",
    "chars": 6722,
    "preview": "on:\n  push:\n    branches:\n      - main\n      - develop\n    tags:\n      - '*'\n  pull_request:\n    paths:\n      - '.github"
  },
  {
    "path": ".github/workflows/generate-api-docs.yml",
    "chars": 1739,
    "preview": "name: Generate API docs\non:\n  push:\n    branches:\n      - main\npermissions:\n  contents: read\n\njobs:\n  api_docs:\n    runs"
  },
  {
    "path": ".github/workflows/npm-build.yml",
    "chars": 699,
    "preview": "name: NPM Build\n\non: [push]\npermissions:\n  contents: read\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    timeout-minutes"
  },
  {
    "path": ".github/workflows/npm-format-check.yml",
    "chars": 430,
    "preview": "name: NPM Format Check\n\non: [push]\n\njobs:\n  format-check:\n    runs-on: ubuntu-latest\n    timeout-minutes: 10\n\n    steps:"
  },
  {
    "path": ".github/workflows/npm-lint.yml",
    "chars": 426,
    "preview": "name: NPM Lint\n\non: [push]\npermissions:\n  contents: read\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    timeout-minutes:"
  },
  {
    "path": ".github/workflows/npm-publish-api.yml",
    "chars": 934,
    "preview": "name: Publish API package to NPM\non:\n  workflow_dispatch\npermissions:\n  contents: read\njobs:\n  build:\n    runs-on: ubunt"
  },
  {
    "path": ".github/workflows/npm-publish-ui.yml",
    "chars": 938,
    "preview": "name: Publish UI package to NPM\non:\n  workflow_dispatch\npermissions:\n  contents: read\njobs:\n  build:\n    runs-on: ubuntu"
  },
  {
    "path": ".github/workflows/npm-typecheck.yml",
    "chars": 716,
    "preview": "name: NPM Typecheck\n\non: [push]\npermissions:\n  contents: read\njobs:\n  build:\n    runs-on: ubuntu-latest\n    timeout-minu"
  },
  {
    "path": ".github/workflows/phpstan.yml",
    "chars": 625,
    "preview": "name: Static code analysis (PHPStan)\non: push\npermissions:\n  contents: read\njobs:\n  phpstan:\n    runs-on: ubuntu-latest\n"
  },
  {
    "path": ".github/workflows/phpunit.yml",
    "chars": 1980,
    "preview": "name: PHPUnit Tests\non: push\npermissions:\n  contents: read\njobs:\n  phpunit:\n    runs-on: ubuntu-latest\n    timeout-minut"
  },
  {
    "path": ".github/workflows/pint.yml",
    "chars": 328,
    "preview": "name: PHP Linting\non: push\npermissions:\n  contents: read\njobs:\n  pint:\n    runs-on: ubuntu-latest\n    timeout-minutes: 1"
  },
  {
    "path": ".github/workflows/playwright.yml",
    "chars": 3457,
    "preview": "name: Playwright Tests\non: [push]\npermissions:\n  contents: read\njobs:\n  test:\n    runs-on: ubuntu-latest\n    timeout-min"
  },
  {
    "path": ".gitignore",
    "chars": 601,
    "preview": "/.phpunit.cache\nnode_modules\ndist\n/public/build\n/public/hot\n/public/storage\n/public/css\n/public/js\n/public/vendor\n/lang/"
  },
  {
    "path": ".prettierignore",
    "chars": 326,
    "preview": "# Ignore build outputs\nnode_modules/\nvendor/\nstorage/\nbootstrap/cache/\npublic/build/\npublic/hot/\n\n# Ignore lock files\npa"
  },
  {
    "path": ".prettierrc.json",
    "chars": 157,
    "preview": "{\n    \"trailingComma\": \"es5\",\n    \"tabWidth\": 4,\n    \"singleQuote\": true,\n    \"bracketSameLine\": true,\n    \"quoteProps\":"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 2045,
    "preview": "# Code of Conduct\n\nThe goal is to create a community that is open and welcoming to all individuals.\nTo achieve this, we "
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 5765,
    "preview": "# Contributing to solidtime\n\nContributions are greatly apprecited, please make sure to read the rules and vision for sol"
  },
  {
    "path": "LICENSE.md",
    "chars": 34202,
    "preview": "GNU Affero General Public License\n=================================\n\n_Version 3, 19 November 2007_\n_Copyright © 2007 Fre"
  },
  {
    "path": "README.md",
    "chars": 3185,
    "preview": "# solidtime - The modern Open-Source Time Tracker\n\n[![GitHub License](https://img.shields.io/github/license/solidtime-io"
  },
  {
    "path": "SECURITY.md",
    "chars": 189,
    "preview": "# Security Policy\n\n## Reporting a Vulnerability\n\nIf you discover a security vulnerability regarding this project, please"
  },
  {
    "path": "app/Actions/Fortify/CreateNewUser.php",
    "chars": 3939,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Fortify;\n\nuse App\\Enums\\Weekday;\nuse App\\Events\\NewsletterRegiste"
  },
  {
    "path": "app/Actions/Fortify/PasswordValidationRules.php",
    "chars": 437,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Fortify;\n\nuse Illuminate\\Contracts\\Validation\\Rule;\nuse Illuminat"
  },
  {
    "path": "app/Actions/Fortify/ResetUserPassword.php",
    "chars": 719,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Fortify;\n\nuse App\\Models\\User;\nuse Illuminate\\Support\\Facades\\Has"
  },
  {
    "path": "app/Actions/Fortify/UpdateUserPassword.php",
    "chars": 950,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Fortify;\n\nuse App\\Models\\User;\nuse Illuminate\\Support\\Facades\\Has"
  },
  {
    "path": "app/Actions/Fortify/UpdateUserProfileInformation.php",
    "chars": 2394,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Fortify;\n\nuse App\\Enums\\Weekday;\nuse App\\Models\\User;\nuse Illumin"
  },
  {
    "path": "app/Actions/Jetstream/AddOrganizationMember.php",
    "chars": 2984,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Jetstream;\n\nuse App\\Enums\\Role;\nuse App\\Models\\Organization;\nuse "
  },
  {
    "path": "app/Actions/Jetstream/CreateOrganization.php",
    "chars": 1726,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Jetstream;\n\nuse App\\Events\\AfterCreateOrganization;\nuse App\\Model"
  },
  {
    "path": "app/Actions/Jetstream/DeleteOrganization.php",
    "chars": 469,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Jetstream;\n\nuse App\\Models\\Organization;\nuse App\\Service\\Deletion"
  },
  {
    "path": "app/Actions/Jetstream/DeleteUser.php",
    "chars": 706,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Jetstream;\n\nuse App\\Exceptions\\Api\\ApiException;\nuse App\\Models\\U"
  },
  {
    "path": "app/Actions/Jetstream/InviteOrganizationMember.php",
    "chars": 550,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Jetstream;\n\nuse App\\Exceptions\\MovedToApiException;\nuse App\\Model"
  },
  {
    "path": "app/Actions/Jetstream/RemoveOrganizationMember.php",
    "chars": 531,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Jetstream;\n\nuse App\\Exceptions\\MovedToApiException;\nuse App\\Model"
  },
  {
    "path": "app/Actions/Jetstream/UpdateMemberRole.php",
    "chars": 501,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Jetstream;\n\nuse App\\Enums\\Role;\nuse App\\Exceptions\\MovedToApiExce"
  },
  {
    "path": "app/Actions/Jetstream/UpdateOrganization.php",
    "chars": 1266,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Jetstream;\n\nuse App\\Models\\Organization;\nuse App\\Models\\User;\nuse"
  },
  {
    "path": "app/Actions/Jetstream/ValidateOrganizationDeletion.php",
    "chars": 734,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Actions\\Jetstream;\n\nuse App\\Models\\Organization;\nuse App\\Models\\User;\nuse"
  },
  {
    "path": "app/Console/Commands/Admin/OrganizationDeleteCommand.php",
    "chars": 1501,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands\\Admin;\n\nuse App\\Models\\Organization;\nuse App\\Service\\Del"
  },
  {
    "path": "app/Console/Commands/Admin/UserCreateCommand.php",
    "chars": 2773,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands\\Admin;\n\nuse App\\Enums\\Weekday;\nuse App\\Models\\Organizati"
  },
  {
    "path": "app/Console/Commands/Admin/UserVerifyCommand.php",
    "chars": 1424,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands\\Admin;\n\nuse App\\Models\\User;\nuse Illuminate\\Auth\\Events\\"
  },
  {
    "path": "app/Console/Commands/Auth/AuthSendReminderForExpiringApiTokensCommand.php",
    "chars": 4117,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands\\Auth;\n\nuse App\\Mail\\AuthApiTokenExpirationReminderMail;\n"
  },
  {
    "path": "app/Console/Commands/Correction/CorrectionPlaceholderMembersCommand.php",
    "chars": 1755,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands\\Correction;\n\nuse App\\Enums\\Role;\nuse App\\Models\\Member;\n"
  },
  {
    "path": "app/Console/Commands/Report/ReportSetExpiredToPrivateCommand.php",
    "chars": 2280,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands\\Report;\n\nuse App\\Models\\Report;\nuse Illuminate\\Console\\C"
  },
  {
    "path": "app/Console/Commands/SelfHost/SelfHostCheckForUpdateCommand.php",
    "chars": 1071,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands\\SelfHost;\n\nuse App\\Service\\ApiService;\nuse Illuminate\\Co"
  },
  {
    "path": "app/Console/Commands/SelfHost/SelfHostDatabaseConsistency.php",
    "chars": 4641,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands\\SelfHost;\n\nuse Illuminate\\Console\\Command;\nuse Illuminat"
  },
  {
    "path": "app/Console/Commands/SelfHost/SelfHostGenerateKeysCommand.php",
    "chars": 2192,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands\\SelfHost;\n\nuse Illuminate\\Console\\Command;\nuse Illuminat"
  },
  {
    "path": "app/Console/Commands/SelfHost/SelfHostTelemetryCommand.php",
    "chars": 841,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands\\SelfHost;\n\nuse App\\Service\\ApiService;\nuse Illuminate\\Co"
  },
  {
    "path": "app/Console/Commands/Test/TestEmailCommand.php",
    "chars": 936,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands\\Test;\n\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Ma"
  },
  {
    "path": "app/Console/Commands/Test/TestJobCommand.php",
    "chars": 766,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands\\Test;\n\nuse App\\Jobs\\Test\\TestJob;\nuse App\\Models\\User;\nu"
  },
  {
    "path": "app/Console/Commands/Test/TestOutputCommand.php",
    "chars": 663,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands\\Test;\n\nuse Illuminate\\Console\\Command;\n\nclass TestOutput"
  },
  {
    "path": "app/Console/Commands/TimeEntry/TimeEntrySendStillRunningMailsCommand.php",
    "chars": 2664,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console\\Commands\\TimeEntry;\n\nuse App\\Mail\\TimeEntryStillRunningMail;\nuse "
  },
  {
    "path": "app/Console/Kernel.php",
    "chars": 2185,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Console;\n\nuse Illuminate\\Console\\Scheduling\\Schedule;\nuse Illuminate\\Foun"
  },
  {
    "path": "app/Enums/CurrencyFormat.php",
    "chars": 814,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums;\n\nuse Datomatic\\LaravelEnumHelper\\LaravelEnumHelper;\n\nenum Currency"
  },
  {
    "path": "app/Enums/DateFormat.php",
    "chars": 1334,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums;\n\nuse Datomatic\\LaravelEnumHelper\\LaravelEnumHelper;\n\nenum DateForm"
  },
  {
    "path": "app/Enums/ExportFormat.php",
    "chars": 694,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums;\n\nuse Maatwebsite\\Excel\\Excel;\n\nenum ExportFormat: string\n{\n    cas"
  },
  {
    "path": "app/Enums/IntervalFormat.php",
    "chars": 714,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums;\n\nuse Datomatic\\LaravelEnumHelper\\LaravelEnumHelper;\n\nenum Interval"
  },
  {
    "path": "app/Enums/NumberFormat.php",
    "chars": 823,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums;\n\nuse Datomatic\\LaravelEnumHelper\\LaravelEnumHelper;\n\n/**\n * @info "
  },
  {
    "path": "app/Enums/Role.php",
    "chars": 229,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums;\n\nenum Role: string\n{\n    case Owner = 'owner';\n    case Admin = 'a"
  },
  {
    "path": "app/Enums/TimeEntryAggregationType.php",
    "chars": 1527,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums;\n\nuse Datomatic\\LaravelEnumHelper\\LaravelEnumHelper;\n\nenum TimeEntr"
  },
  {
    "path": "app/Enums/TimeEntryAggregationTypeInterval.php",
    "chars": 201,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums;\n\nenum TimeEntryAggregationTypeInterval: string\n{\n    case Day = 'd"
  },
  {
    "path": "app/Enums/TimeEntryRoundingType.php",
    "chars": 248,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums;\n\nuse Datomatic\\LaravelEnumHelper\\LaravelEnumHelper;\n\nenum TimeEntr"
  },
  {
    "path": "app/Enums/TimeFormat.php",
    "chars": 550,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums;\n\nuse Datomatic\\LaravelEnumHelper\\LaravelEnumHelper;\n\nenum TimeForm"
  },
  {
    "path": "app/Enums/Weekday.php",
    "chars": 2025,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Enums;\n\nuse Datomatic\\LaravelEnumHelper\\LaravelEnumHelper;\nuse Illuminate"
  },
  {
    "path": "app/Events/AfterCreateOrganization.php",
    "chars": 570,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Events;\n\nuse App\\Models\\Organization;\nuse Illuminate\\Foundation\\Events\\Di"
  },
  {
    "path": "app/Events/BeforeOrganizationDeletion.php",
    "chars": 350,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Events;\n\nuse App\\Models\\Organization;\nuse Illuminate\\Foundation\\Events\\Di"
  },
  {
    "path": "app/Events/DatabaseSeederAfterSeed.php",
    "chars": 198,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Events;\n\nuse Illuminate\\Foundation\\Events\\Dispatchable;\n\nclass DatabaseSe"
  },
  {
    "path": "app/Events/DatabaseSeederBeforeDelete.php",
    "chars": 201,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Events;\n\nuse Illuminate\\Foundation\\Events\\Dispatchable;\n\nclass DatabaseSe"
  },
  {
    "path": "app/Events/MemberMadeToPlaceholder.php",
    "chars": 447,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Events;\n\nuse App\\Models\\Member;\nuse App\\Models\\Organization;\nuse Illumina"
  },
  {
    "path": "app/Events/MemberRemoved.php",
    "chars": 437,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Events;\n\nuse App\\Models\\Member;\nuse App\\Models\\Organization;\nuse Illumina"
  },
  {
    "path": "app/Events/NewsletterRegistered.php",
    "chars": 457,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Events;\n\nuse Illuminate\\Foundation\\Events\\Dispatchable;\n\nclass Newsletter"
  },
  {
    "path": "app/Exceptions/Api/ApiException.php",
    "chars": 1409,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nuse Exception;\nuse Illuminate\\Http\\JsonResponse;\nuse Ill"
  },
  {
    "path": "app/Exceptions/Api/CanNotDeleteUserWhoIsOwnerOfOrganizationWithMultipleMembers.php",
    "chars": 259,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass CanNotDeleteUserWhoIsOwnerOfOrganizationWithMultip"
  },
  {
    "path": "app/Exceptions/Api/CanNotRemoveOwnerFromOrganization.php",
    "chars": 201,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass CanNotRemoveOwnerFromOrganization extends ApiExcep"
  },
  {
    "path": "app/Exceptions/Api/ChangingRoleOfPlaceholderIsNotAllowed.php",
    "chars": 210,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass ChangingRoleOfPlaceholderIsNotAllowed extends ApiE"
  },
  {
    "path": "app/Exceptions/Api/ChangingRoleToPlaceholderIsNotAllowed.php",
    "chars": 210,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass ChangingRoleToPlaceholderIsNotAllowed extends ApiE"
  },
  {
    "path": "app/Exceptions/Api/EntityStillInUseApiException.php",
    "chars": 824,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass EntityStillInUseApiException extends ApiException\n"
  },
  {
    "path": "app/Exceptions/Api/FeatureIsNotAvailableInFreePlanApiException.php",
    "chars": 210,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass FeatureIsNotAvailableInFreePlanApiException extend"
  },
  {
    "path": "app/Exceptions/Api/InactiveUserCanNotBeUsedApiException.php",
    "chars": 195,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass InactiveUserCanNotBeUsedApiException extends ApiEx"
  },
  {
    "path": "app/Exceptions/Api/InvitationForTheEmailAlreadyExistsApiException.php",
    "chars": 215,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass InvitationForTheEmailAlreadyExistsApiException ext"
  },
  {
    "path": "app/Exceptions/Api/OnlyOwnerCanChangeOwnership.php",
    "chars": 188,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass OnlyOwnerCanChangeOwnership extends ApiException\n{"
  },
  {
    "path": "app/Exceptions/Api/OnlyPlaceholdersCanBeMergedIntoAnotherMember.php",
    "chars": 225,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass OnlyPlaceholdersCanBeMergedIntoAnotherMember exten"
  },
  {
    "path": "app/Exceptions/Api/OrganizationHasNoSubscriptionButMultipleMembersException.php",
    "chars": 239,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass OrganizationHasNoSubscriptionButMultipleMembersExc"
  },
  {
    "path": "app/Exceptions/Api/OrganizationNeedsAtLeastOneOwner.php",
    "chars": 199,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass OrganizationNeedsAtLeastOneOwner extends ApiExcept"
  },
  {
    "path": "app/Exceptions/Api/OverlappingTimeEntryApiException.php",
    "chars": 184,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass OverlappingTimeEntryApiException extends ApiExcept"
  },
  {
    "path": "app/Exceptions/Api/PdfRendererIsNotConfiguredException.php",
    "chars": 195,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass PdfRendererIsNotConfiguredException extends ApiExc"
  },
  {
    "path": "app/Exceptions/Api/PersonalAccessClientIsNotConfiguredException.php",
    "chars": 214,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass PersonalAccessClientIsNotConfiguredException exten"
  },
  {
    "path": "app/Exceptions/Api/ThisPlaceholderCanNotBeInvitedUseTheMergeToolInsteadException.php",
    "chars": 267,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass ThisPlaceholderCanNotBeInvitedUseTheMergeToolInste"
  },
  {
    "path": "app/Exceptions/Api/TimeEntryCanNotBeRestartedApiException.php",
    "chars": 199,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass TimeEntryCanNotBeRestartedApiException extends Api"
  },
  {
    "path": "app/Exceptions/Api/TimeEntryStillRunningApiException.php",
    "chars": 187,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass TimeEntryStillRunningApiException extends ApiExcep"
  },
  {
    "path": "app/Exceptions/Api/UserIsAlreadyMemberOfOrganizationApiException.php",
    "chars": 213,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass UserIsAlreadyMemberOfOrganizationApiException exte"
  },
  {
    "path": "app/Exceptions/Api/UserIsAlreadyMemberOfProjectApiException.php",
    "chars": 203,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass UserIsAlreadyMemberOfProjectApiException extends A"
  },
  {
    "path": "app/Exceptions/Api/UserNotPlaceholderApiException.php",
    "chars": 180,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions\\Api;\n\nclass UserNotPlaceholderApiException extends ApiExceptio"
  },
  {
    "path": "app/Exceptions/Handler.php",
    "chars": 1103,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions;\n\nuse Illuminate\\Foundation\\Exceptions\\Handler as ExceptionHan"
  },
  {
    "path": "app/Exceptions/MovedToApiException.php",
    "chars": 267,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Exceptions;\n\nuse Symfony\\Component\\HttpKernel\\Exception\\HttpException;\n\nc"
  },
  {
    "path": "app/Extensions/Auditing/Resolvers/CustomIpAddressResolver.php",
    "chars": 808,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Extensions\\Auditing\\Resolvers;\n\nuse Illuminate\\Support\\Facades\\Request;\nu"
  },
  {
    "path": "app/Extensions/Fortify/CustomLoginResponse.php",
    "chars": 676,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Extensions\\Fortify;\n\nuse Illuminate\\Http\\Request;\nuse Inertia\\Inertia;\nus"
  },
  {
    "path": "app/Extensions/Fortify/CustomTwoFactorLoginResponse.php",
    "chars": 761,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Extensions\\Fortify;\n\nuse Illuminate\\Http\\JsonResponse;\nuse Illuminate\\Htt"
  },
  {
    "path": "app/Extensions/Scramble/ApiExceptionTypeToSchema.php",
    "chars": 1802,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Extensions\\Scramble;\n\nuse App\\Exceptions\\Api\\ApiException;\nuse Dedoc\\Scra"
  },
  {
    "path": "app/Extensions/Scramble/PaginatedResourceCollectionTypeToSchema.php",
    "chars": 4792,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Extensions\\Scramble;\n\nuse App\\Http\\Resources\\PaginatedResourceCollection;"
  },
  {
    "path": "app/Filament/Resources/AuditResource/Pages/CreateAudit.php",
    "chars": 279,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\AuditResource\\Pages;\n\nuse App\\Filament\\Resources\\Audit"
  },
  {
    "path": "app/Filament/Resources/AuditResource/Pages/ListAudits.php",
    "chars": 357,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\AuditResource\\Pages;\n\nuse App\\Filament\\Resources\\Audit"
  },
  {
    "path": "app/Filament/Resources/AuditResource/Pages/ViewAudit.php",
    "chars": 273,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\AuditResource\\Pages;\n\nuse App\\Filament\\Resources\\Audit"
  },
  {
    "path": "app/Filament/Resources/AuditResource.php",
    "chars": 3097,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Filament\\Resources\\AuditResource\\Pages;\nuse "
  },
  {
    "path": "app/Filament/Resources/ClientResource/Pages/CreateClient.php",
    "chars": 283,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\ClientResource\\Pages;\n\nuse App\\Filament\\Resources\\Clie"
  },
  {
    "path": "app/Filament/Resources/ClientResource/Pages/EditClient.php",
    "chars": 474,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\ClientResource\\Pages;\n\nuse App\\Filament\\Resources\\Clie"
  },
  {
    "path": "app/Filament/Resources/ClientResource/Pages/ListClients.php",
    "chars": 476,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\ClientResource\\Pages;\n\nuse App\\Filament\\Resources\\Clie"
  },
  {
    "path": "app/Filament/Resources/ClientResource.php",
    "chars": 2956,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Filament\\Resources\\ClientResource\\Pages;\nuse"
  },
  {
    "path": "app/Filament/Resources/FailedJobResource/Pages/ListFailedJobs.php",
    "chars": 1483,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\FailedJobResource\\Pages;\n\nuse App\\Filament\\Resources\\F"
  },
  {
    "path": "app/Filament/Resources/FailedJobResource/Pages/ViewFailedJobs.php",
    "chars": 290,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\FailedJobResource\\Pages;\n\nuse App\\Filament\\Resources\\F"
  },
  {
    "path": "app/Filament/Resources/FailedJobResource.php",
    "chars": 4725,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Filament\\Resources\\FailedJobResource\\Pages\\L"
  },
  {
    "path": "app/Filament/Resources/OrganizationInvitationResource/Pages/EditOrganizationInvitation.php",
    "chars": 538,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\OrganizationInvitationResource\\Pages;\n\nuse App\\Filamen"
  },
  {
    "path": "app/Filament/Resources/OrganizationInvitationResource/Pages/ListOrganizationInvitations.php",
    "chars": 434,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\OrganizationInvitationResource\\Pages;\n\nuse App\\Filamen"
  },
  {
    "path": "app/Filament/Resources/OrganizationInvitationResource/Pages/ViewOrganizationInvitation.php",
    "chars": 546,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\OrganizationInvitationResource\\Pages;\n\nuse App\\Filamen"
  },
  {
    "path": "app/Filament/Resources/OrganizationInvitationResource.php",
    "chars": 3885,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Enums\\Role;\nuse App\\Filament\\Resources\\Organ"
  },
  {
    "path": "app/Filament/Resources/OrganizationResource/Actions/DeleteOrganization.php",
    "chars": 1303,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\OrganizationResource\\Actions;\n\nuse App\\Exceptions\\Api\\"
  },
  {
    "path": "app/Filament/Resources/OrganizationResource/Pages/CreateOrganization.php",
    "chars": 816,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\OrganizationResource\\Pages;\n\nuse App\\Enums\\Role;\nuse A"
  },
  {
    "path": "app/Filament/Resources/OrganizationResource/Pages/EditOrganization.php",
    "chars": 460,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\OrganizationResource\\Pages;\n\nuse App\\Filament\\Resource"
  },
  {
    "path": "app/Filament/Resources/OrganizationResource/Pages/ListOrganizations.php",
    "chars": 500,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\OrganizationResource\\Pages;\n\nuse App\\Filament\\Resource"
  },
  {
    "path": "app/Filament/Resources/OrganizationResource/Pages/ViewOrganization.php",
    "chars": 506,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\OrganizationResource\\Pages;\n\nuse App\\Filament\\Resource"
  },
  {
    "path": "app/Filament/Resources/OrganizationResource/RelationManagers/InvitationsRelationManager.php",
    "chars": 2985,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\OrganizationResource\\RelationManagers;\n\nuse App\\Enums\\"
  },
  {
    "path": "app/Filament/Resources/OrganizationResource/RelationManagers/UsersRelationManager.php",
    "chars": 5801,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\OrganizationResource\\RelationManagers;\n\nuse App\\Enums\\"
  },
  {
    "path": "app/Filament/Resources/OrganizationResource.php",
    "chars": 10901,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Enums\\CurrencyFormat;\nuse App\\Enums\\DateForm"
  },
  {
    "path": "app/Filament/Resources/ProjectMemberResource/Pages/CreateProjectMember.php",
    "chars": 311,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\ProjectMemberResource\\Pages;\n\nuse App\\Filament\\Resourc"
  },
  {
    "path": "app/Filament/Resources/ProjectMemberResource/Pages/EditProjectMember.php",
    "chars": 502,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\ProjectMemberResource\\Pages;\n\nuse App\\Filament\\Resourc"
  },
  {
    "path": "app/Filament/Resources/ProjectMemberResource/Pages/ListProjectMembers.php",
    "chars": 504,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\ProjectMemberResource\\Pages;\n\nuse App\\Filament\\Resourc"
  },
  {
    "path": "app/Filament/Resources/ProjectMemberResource/Pages/ViewProjectMembers.php",
    "chars": 511,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\ProjectMemberResource\\Pages;\n\nuse App\\Filament\\Resourc"
  },
  {
    "path": "app/Filament/Resources/ProjectMemberResource.php",
    "chars": 2834,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Filament\\Resources\\ProjectMemberResource\\Pag"
  },
  {
    "path": "app/Filament/Resources/ProjectResource/Pages/CreateProject.php",
    "chars": 287,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\ProjectResource\\Pages;\n\nuse App\\Filament\\Resources\\Pro"
  },
  {
    "path": "app/Filament/Resources/ProjectResource/Pages/EditProject.php",
    "chars": 478,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\ProjectResource\\Pages;\n\nuse App\\Filament\\Resources\\Pro"
  },
  {
    "path": "app/Filament/Resources/ProjectResource/Pages/ListProjects.php",
    "chars": 480,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\ProjectResource\\Pages;\n\nuse App\\Filament\\Resources\\Pro"
  },
  {
    "path": "app/Filament/Resources/ProjectResource/RelationManagers/ProjectMembersRelationManager.php",
    "chars": 1795,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\ProjectResource\\RelationManagers;\n\nuse App\\Filament\\Re"
  },
  {
    "path": "app/Filament/Resources/ProjectResource.php",
    "chars": 3499,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Filament\\Resources\\ProjectResource\\Pages;\nus"
  },
  {
    "path": "app/Filament/Resources/ReportResource/Pages/EditReport.php",
    "chars": 474,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\ReportResource\\Pages;\n\nuse App\\Filament\\Resources\\Repo"
  },
  {
    "path": "app/Filament/Resources/ReportResource/Pages/ListReports.php",
    "chars": 370,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\ReportResource\\Pages;\n\nuse App\\Filament\\Resources\\Repo"
  },
  {
    "path": "app/Filament/Resources/ReportResource/Pages/ViewReport.php",
    "chars": 482,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\ReportResource\\Pages;\n\nuse App\\Filament\\Resources\\Repo"
  },
  {
    "path": "app/Filament/Resources/ReportResource.php",
    "chars": 5106,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Filament\\Resources\\ReportResource\\Pages;\nuse"
  },
  {
    "path": "app/Filament/Resources/TagResource/Pages/CreateTag.php",
    "chars": 271,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\TagResource\\Pages;\n\nuse App\\Filament\\Resources\\TagReso"
  },
  {
    "path": "app/Filament/Resources/TagResource/Pages/EditTag.php",
    "chars": 462,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\TagResource\\Pages;\n\nuse App\\Filament\\Resources\\TagReso"
  },
  {
    "path": "app/Filament/Resources/TagResource/Pages/ListTags.php",
    "chars": 464,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\TagResource\\Pages;\n\nuse App\\Filament\\Resources\\TagReso"
  },
  {
    "path": "app/Filament/Resources/TagResource.php",
    "chars": 2928,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Filament\\Resources\\TagResource\\Pages;\nuse Ap"
  },
  {
    "path": "app/Filament/Resources/TaskResource/Pages/CreateTask.php",
    "chars": 275,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\TaskResource\\Pages;\n\nuse App\\Filament\\Resources\\TaskRe"
  },
  {
    "path": "app/Filament/Resources/TaskResource/Pages/EditTask.php",
    "chars": 466,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\TaskResource\\Pages;\n\nuse App\\Filament\\Resources\\TaskRe"
  },
  {
    "path": "app/Filament/Resources/TaskResource/Pages/ListTasks.php",
    "chars": 468,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\TaskResource\\Pages;\n\nuse App\\Filament\\Resources\\TaskRe"
  },
  {
    "path": "app/Filament/Resources/TaskResource.php",
    "chars": 3063,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Filament\\Resources\\TaskResource\\Pages;\nuse A"
  },
  {
    "path": "app/Filament/Resources/TimeEntryResource/Pages/CreateTimeEntry.php",
    "chars": 851,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\TimeEntryResource\\Pages;\n\nuse App\\Filament\\Resources\\T"
  },
  {
    "path": "app/Filament/Resources/TimeEntryResource/Pages/EditTimeEntry.php",
    "chars": 1040,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\TimeEntryResource\\Pages;\n\nuse App\\Filament\\Resources\\T"
  },
  {
    "path": "app/Filament/Resources/TimeEntryResource/Pages/ListTimeEntries.php",
    "chars": 489,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\TimeEntryResource\\Pages;\n\nuse App\\Filament\\Resources\\T"
  },
  {
    "path": "app/Filament/Resources/TimeEntryResource.php",
    "chars": 4973,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Filament\\Resources\\TimeEntryResource\\Pages;\n"
  },
  {
    "path": "app/Filament/Resources/TokenResource/Pages/ListTokens.php",
    "chars": 366,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\TokenResource\\Pages;\n\nuse App\\Filament\\Resources\\Token"
  },
  {
    "path": "app/Filament/Resources/TokenResource/Pages/ViewToken.php",
    "chars": 363,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\TokenResource\\Pages;\n\nuse App\\Filament\\Resources\\Token"
  },
  {
    "path": "app/Filament/Resources/TokenResource.php",
    "chars": 5096,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Filament\\Resources\\TokenResource\\Pages;\nuse "
  },
  {
    "path": "app/Filament/Resources/UserResource/Actions/DeleteUser.php",
    "chars": 1263,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\UserResource\\Actions;\n\nuse App\\Exceptions\\Api\\ApiExcep"
  },
  {
    "path": "app/Filament/Resources/UserResource/Pages/CreateUser.php",
    "chars": 810,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\UserResource\\Pages;\n\nuse App\\Enums\\Weekday;\nuse App\\Fi"
  },
  {
    "path": "app/Filament/Resources/UserResource/Pages/EditUser.php",
    "chars": 528,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\UserResource\\Pages;\n\nuse App\\Filament\\Resources\\UserRe"
  },
  {
    "path": "app/Filament/Resources/UserResource/Pages/ListUsers.php",
    "chars": 468,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\UserResource\\Pages;\n\nuse App\\Filament\\Resources\\UserRe"
  },
  {
    "path": "app/Filament/Resources/UserResource/Pages/ViewUser.php",
    "chars": 590,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\UserResource\\Pages;\n\nuse App\\Filament\\Resources\\UserRe"
  },
  {
    "path": "app/Filament/Resources/UserResource/RelationManagers/OrganizationsRelationManager.php",
    "chars": 3825,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\UserResource\\RelationManagers;\n\nuse App\\Enums\\Role;\nus"
  },
  {
    "path": "app/Filament/Resources/UserResource/RelationManagers/OwnedOrganizationsRelationManager.php",
    "chars": 1661,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources\\UserResource\\RelationManagers;\n\nuse App\\Filament\\Resou"
  },
  {
    "path": "app/Filament/Resources/UserResource.php",
    "chars": 9992,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Resources;\n\nuse App\\Enums\\Weekday;\nuse App\\Exceptions\\Api\\ApiExc"
  },
  {
    "path": "app/Filament/Widgets/ActiveUserOverview.php",
    "chars": 1485,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Widgets;\n\nuse App\\Models\\TimeEntry;\nuse App\\Models\\User;\nuse Fil"
  },
  {
    "path": "app/Filament/Widgets/ServerOverview.php",
    "chars": 1028,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Widgets;\n\nuse Filament\\Widgets\\Widget;\nuse Illuminate\\Support\\Fa"
  },
  {
    "path": "app/Filament/Widgets/TimeEntriesCreated.php",
    "chars": 1873,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Widgets;\n\nuse App\\Models\\TimeEntry;\nuse Filament\\Widgets\\ChartWi"
  },
  {
    "path": "app/Filament/Widgets/TimeEntriesImported.php",
    "chars": 1874,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Widgets;\n\nuse App\\Models\\TimeEntry;\nuse Filament\\Widgets\\ChartWi"
  },
  {
    "path": "app/Filament/Widgets/UserRegistrations.php",
    "chars": 1880,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Filament\\Widgets;\n\nuse App\\Models\\User;\nuse Filament\\Widgets\\ChartWidget;"
  },
  {
    "path": "app/Http/Controllers/Api/V1/ApiTokenController.php",
    "chars": 3768,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Exceptions\\Api\\PersonalAccessClientIsNo"
  },
  {
    "path": "app/Http/Controllers/Api/V1/ChartController.php",
    "chars": 6091,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Enums\\Role;\nuse App\\Models\\Organization"
  },
  {
    "path": "app/Http/Controllers/Api/V1/ClientController.php",
    "chars": 3707,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Exceptions\\Api\\EntityStillInUseApiExcep"
  },
  {
    "path": "app/Http/Controllers/Api/V1/Controller.php",
    "chars": 1494,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Models\\Organization;\nuse App\\Service\\Bi"
  },
  {
    "path": "app/Http/Controllers/Api/V1/CurrencyController.php",
    "chars": 999,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Http\\Controllers\\Controller;\nuse App\\Se"
  },
  {
    "path": "app/Http/Controllers/Api/V1/ExportController.php",
    "chars": 1052,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Models\\Organization;\nuse App\\Service\\Ex"
  },
  {
    "path": "app/Http/Controllers/Api/V1/ImportController.php",
    "chars": 3357,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Http\\Requests\\V1\\Import\\ImportRequest;\n"
  },
  {
    "path": "app/Http/Controllers/Api/V1/InvitationController.php",
    "chars": 3417,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Exceptions\\Api\\InvitationForTheEmailAlr"
  },
  {
    "path": "app/Http/Controllers/Api/V1/MemberController.php",
    "chars": 7499,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Enums\\Role;\nuse App\\Events\\MemberMadeTo"
  },
  {
    "path": "app/Http/Controllers/Api/V1/OrganizationController.php",
    "chars": 3103,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Enums\\Role;\nuse App\\Http\\Requests\\V1\\Or"
  },
  {
    "path": "app/Http/Controllers/Api/V1/ProjectController.php",
    "chars": 6796,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Enums\\Role;\nuse App\\Exceptions\\Api\\Enti"
  },
  {
    "path": "app/Http/Controllers/Api/V1/ProjectMemberController.php",
    "chars": 5360,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Exceptions\\Api\\InactiveUserCanNotBeUsed"
  },
  {
    "path": "app/Http/Controllers/Api/V1/Public/ReportController.php",
    "chars": 3750,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1\\Public;\n\nuse App\\Enums\\TimeEntryAggregationType;\n"
  },
  {
    "path": "app/Http/Controllers/Api/V1/ReportController.php",
    "chars": 6599,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Enums\\Weekday;\nuse App\\Http\\Requests\\V1"
  },
  {
    "path": "app/Http/Controllers/Api/V1/TagController.php",
    "chars": 2937,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Exceptions\\Api\\EntityStillInUseApiExcep"
  },
  {
    "path": "app/Http/Controllers/Api/V1/TaskController.php",
    "chars": 5944,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Exceptions\\Api\\EntityStillInUseApiExcep"
  },
  {
    "path": "app/Http/Controllers/Api/V1/TimeEntryController.php",
    "chars": 36982,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Enums\\ExportFormat;\nuse App\\Enums\\Role;"
  },
  {
    "path": "app/Http/Controllers/Api/V1/UserController.php",
    "chars": 519,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Http\\Resources\\V1\\User\\UserResource;\nus"
  },
  {
    "path": "app/Http/Controllers/Api/V1/UserMembershipController.php",
    "chars": 868,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Http\\Resources\\V1\\Member\\PersonalMember"
  },
  {
    "path": "app/Http/Controllers/Api/V1/UserTimeEntryController.php",
    "chars": 1312,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Api\\V1;\n\nuse App\\Http\\Resources\\V1\\TimeEntry\\TimeEntryRe"
  },
  {
    "path": "app/Http/Controllers/Controller.php",
    "chars": 1939,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Models\\Member;\nuse App\\Models\\Organization;\nus"
  },
  {
    "path": "app/Http/Controllers/Web/Controller.php",
    "chars": 140,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Web;\n\nabstract class Controller extends \\App\\Http\\Contro"
  },
  {
    "path": "app/Http/Controllers/Web/DashboardController.php",
    "chars": 962,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Web;\n\nuse App\\Enums\\Role;\nuse App\\Service\\DashboardServi"
  },
  {
    "path": "app/Http/Controllers/Web/HealthCheckController.php",
    "chars": 2513,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Web;\n\nuse App\\Http\\Controllers\\Controller;\nuse App\\Model"
  },
  {
    "path": "app/Http/Controllers/Web/HomeController.php",
    "chars": 393,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Controllers\\Web;\n\nuse Illuminate\\Http\\RedirectResponse;\nuse Illumina"
  },
  {
    "path": "app/Http/Kernel.php",
    "chars": 3224,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http;\n\nuse App\\Http\\Middleware\\CheckOrganizationBlocked;\nuse App\\Http\\Mid"
  },
  {
    "path": "app/Http/Middleware/Authenticate.php",
    "chars": 435,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Middleware;\n\nuse Illuminate\\Auth\\Middleware\\Authenticate as Middlewa"
  },
  {
    "path": "app/Http/Middleware/CheckOrganizationBlocked.php",
    "chars": 1094,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Middleware;\n\nuse App\\Exceptions\\Api\\OrganizationHasNoSubscriptionBut"
  },
  {
    "path": "app/Http/Middleware/EncryptCookies.php",
    "chars": 333,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Middleware;\n\nuse Illuminate\\Cookie\\Middleware\\EncryptCookies as Midd"
  },
  {
    "path": "app/Http/Middleware/EnsureEmailIsVerified.php",
    "chars": 839,
    "preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace App\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Http\\Request;\nuse Illuminat"
  }
]

// ... and 1008 more files (download for full content)

About this extraction

This page contains the full source code of the solidtime-io/solidtime GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1208 files (3.9 MB), approximately 1.1M tokens, and a symbol index with 2769 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!