Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ZMS-3253 ZMS-3466 ZMS-3415 ZMS-1891): Replicate frontend validation in the backend for the availability opening hours to improve data integrity and frontend validation messaging #909

Open
wants to merge 205 commits into
base: next
Choose a base branch
from

Conversation

ThomasAFink
Copy link
Member

@ThomasAFink ThomasAFink commented Feb 27, 2025

Pull Request Checklist (Feature Branch to next):

  • Ich habe die neuesten Änderungen aus dem next Branch in meinen Feature-Branch gemergt.
  • Das Code-Review wurde abgeschlossen.
  • Fachliche Tests wurden durchgeführt und sind abgeschlossen.

Summary by CodeRabbit

  • New Features

    • Enhanced scheduling with detailed, formatted conflict messages and clearer error alerts.
    • Updated date picker now prevents selection during maintenance hours and uses refined time ranges.
    • Introduced new sorting options in schedule views and a dedicated view for location-specific availability.
  • Bug Fixes

    • Adjusted appointment slot duration from 12 to 10 minutes.
    • Refined button states and form error handling to improve user feedback.
  • Tests

    • Expanded test scenarios covering overlapping schedules, conflict detection, and validation.

Tom Fink added 30 commits November 12, 2024 12:25
Thomas Fink and others added 27 commits February 7, 2025 21:13
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…ening-hours-of-the-same-appointment-type-must-not-overlap

# Conflicts:
#	zmsadmin/src/Zmsadmin/AvailabilityConflicts.php
#	zmsapi/src/Zmsapi/AvailabilityUpdate.php
#	zmsentities/src/Zmsentities/Availability.php
…ening-hours-of-the-same-appointment-type-must-not-overlap
…ening-hours-of-the-same-appointment-type-must-not-overlap
…ening-hours-of-the-same-appointment-type-must-not-overlap

# Conflicts:
#	zmscalldisplay/package-lock.json
…ening-hours-of-the-same-appointment-type-must-not-overlap
…ening-hours-of-the-same-appointment-type-must-not-overlap
Copy link
Contributor

coderabbitai bot commented Feb 27, 2025

Walkthrough

This pull request makes extensive updates across both the front‐end and back‐end availability management systems. On the client side, conflict aggregation and rendering, error handling, and UI state management in the availability form and layouts have been revised, including new sorting and disabling logic. On the server side, routing definitions, input validation, conflict processing, and availability add/update endpoints have been refactored with additional modular methods and new exception classes. Tests, fixtures, and schemas have been updated accordingly, notably reducing the slot time from 12 to 10 minutes and adding a new availability “kind” property.

Changes

File(s) Change Summary
zmsadmin/js/page/availabilityDay/form/{conflicts,content,datepicker,errors,footerButtons,formButtons,index}.js Improved conflict aggregation/display, enhanced error handling, and updated state logic in form elements (with new input disabling conditions and refined date handling).
zmsadmin/js/page/availabilityDay/layouts/{accordion,page,tableBody,saveBar}.js Enhanced layout components with sorting features, duplicate rendering in page layout, and UI adjustments; integration of new props and state management for error display.
zmsadmin/js/page/availabilityDay/timetable/{graphview,index,scopeview}.js Removed outdated footer renderings, introduced a new ScopeView component for scope-specific availability display, and streamlined timetable rendering.
zmsadmin/js/page/availabilityDay/helpers.js Enhanced state management by accepting additional parameters and adding functions for time rounding and dynamic availability calculations.
zmsadmin/js/page/availabilityDay/validate.js Expanded validation logic with modular functions for null checks, time format validation, weekday selection, and bookable day range verification.
zmsadmin/routing.php Added a new route for retrieving availability by scope and reformatted existing route definitions for consistent spacing and clarity.
zmsapi/src/Zmsapi/{AvailabilityAdd,AvailabilityUpdate,Exception/*}.php Refactored add/update flows to include comprehensive input validation, modular conflict checking, and improved error handling with new specific exceptions (e.g., AvailabilityAddFailed).
zmsentities/{schema/{availability.json,dereferenced/availability.json,appointment.json},src/Zmsentities/{Availability,Collection/AvailabilityList}.php} Reduced slotTimeInMinutes from 12 to 10, added a new "kind" property to the schema, and introduced additional validation methods and conflict-checking functionality in the Availability entity and its collection.
zmsadmin/tests/{Zmsadmin/*,fixtures/*} and zmsdb/tests/* Updated fixtures and test suites to align with new slot durations, enhanced conflict scenarios, and detailed assertions (including changes in expected timings and additional edge case tests).
zmsdb/src/Zmsdb/Process.php Modified conflict detection by replacing a generic conflict retrieval call with a method specifically checking against existing availabilities.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant AvailabilityPage
    participant API
    participant SaveBar

    User->>AvailabilityPage: Initiate availability update
    AvailabilityPage->>API: POST /availability/save/{id} with payload
    API-->>AvailabilityPage: Return update confirmation
    AvailabilityPage->>SaveBar: updateSaveBarState(type, success)
    SaveBar-->>User: Display success/error message
Loading
sequenceDiagram
    participant Form
    participant ConflictModule
    participant Validator

    Form->>ConflictModule: Call renderConflictList()
    ConflictModule->>Validator: Check for existing conflict entries
    Validator-->>ConflictModule: Return conflict details with dates
    ConflictModule-->>Form: Render conflict messages with formatted <br /> tags
Loading

Possibly related PRs

Suggested reviewers

  • manjencic

Poem

I’m a rabbit, hopping fast,
In fields of code that just came to pass.
Conflicts are sorted and errors tamed,
New routes and updates proudly named.
With each new line, I bounce with glee—
Hoppy changes for all to see! 🐇
CodeRabbit Inc. cheers in harmony!

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (34)
zmsapi/src/Zmsapi/Exception/Availability/AvailabilityAddFailed.php (1)

5-7: Documentation could be improved for clearer purpose

The documentation comment is quite generic and doesn't explain the specific purpose of this exception class.

-/**
- * example class to generate an exception
- */
+/**
+ * Exception thrown when a new availability creation fails, typically due to conflicts
+ * with existing availability entries.
+ */
zmsadmin/js/page/availabilityDay/form/index.js (1)

46-50: New error detection logic improves validation workflow.

The added hasErrors constant provides a clear way to determine if there are any validation errors present.

Consider simplifying the ternary expression by directly using the boolean evaluation:

-const hasErrors = (
-    (
-        this.props.errorList &&
-        Object.keys(this.props.errorList).length
-    )) ? true : false
+const hasErrors = !!(this.props.errorList && Object.keys(this.props.errorList).length)
🧰 Tools
🪛 Biome (1.9.4)

[error] 46-50: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

zmsadmin/js/page/availabilityDay/layouts/accordion.js (1)

172-172: Simplify boolean expression

The ternary operator here is unnecessary since you're already returning a boolean value.

-                        hasConflicts={Object.keys(this.props.conflictList.itemList).length ? true : false}
+                        hasConflicts={Object.keys(this.props.conflictList.itemList).length > 0}
🧰 Tools
🪛 Biome (1.9.4)

[error] 172-172: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

zmsadmin/js/page/availabilityDay/layouts/tableBody.js (2)

214-214: Use optional chaining

Use optional chaining for safer property access.

-                    <td>{availabilityType && availabilityType.name ? availabilityType.name : ""}</td>
+                    <td>{availabilityType?.name || ""}</td>
🧰 Tools
🪛 Biome (1.9.4)

[error] 214-214: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


89-118: Consider extracting sortable column header to a component

The table headers contain repeated code for each sortable column. Consider extracting this pattern to a reusable component to improve maintainability.

zmsadmin/js/page/availabilityDay/form/content.js (3)

24-24: Address the unnecessary use of boolean literals in calenderDisabled.
Static analysis flagged the ternary expression data.type && data.slotTimeInMinutes ? false : true. This can be simplified to:

-const calenderDisabled = data.type && data.slotTimeInMinutes ? false : true;
+const calenderDisabled = !(data.type && data.slotTimeInMinutes);
🧰 Tools
🪛 Biome (1.9.4)

[error] 24-24: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


41-68: Consider extracting the “unsafedSpontaneous” section into a reusable component.
The code block providing guidance for unsaved spontaneous openings is fairly large. Extracting it into a dedicated component (e.g., UnsafedSpontaneousNotice) could reduce clutter in this file.


163-165: Avoid potential confusion with repeated inline forms.
Multiple FormGroup elements within the “Terminabstand” section are correct for user input clarity, but consider grouping them if potential expansions or conditionals arise. This fosters better maintainability.

Also applies to: 173-173, 176-176, 178-179

zmsadmin/js/page/availabilityDay/saveBar.js (1)

25-35: Refine or localize the user feedback strings.
The getMessage() function uses string literals for success/error messages. Consider localizing them if i18n is required, or ensuring consistent capitalization and styling across the app.

zmsapi/tests/Zmsapi/AvailabilityUpdateTest.php (2)

97-105: Mismatch between comment and actual offset.
Line 102 says “// 2 days in the future” yet uses (20 * 24 * 60 * 60). Correct the comment to avoid confusion.

Apply this small fix:

-// 2 days in the future
+// 20 days in the future

110-112: Similarly correct the day offset in the dayoff array.
The code uses (70 * 24 * 60 * 60) but the comment says “7 days in the future.” Ensure the comment is updated appropriately.

zmsadmin/src/Zmsadmin/AvailabilityListByScope.php (2)

31-33: Consider adding stricter date format validation.
While isString() ensures the parameters are strings, there is no guarantee they represent valid dates (e.g., "abc" would pass). You could enhance data integrity by verifying they match an expected date format.


58-63: Refine exception handling for missing availability data.
Matching by string comparison on $exception->template may be brittle if exception classes or messages change. Consider catching a more specific exception class or applying an internal code property to streamline error handling and reduce the risk of false matches.

zmsadmin/js/page/availabilityDay/form/footerButtons.js (1)

47-73: Simplify the complex disabled conditions.
Buttons have lengthy inline conditions that can impact readability and maintenance. Consider extracting them to well-named helper variables or a small function.

zmsapi/src/Zmsapi/AvailabilityAdd.php (4)

43-52: Suggestion: Provide a clearer error message.
While the validation logic here is correct, throwing a generic BadRequestException without a descriptive message may hamper debugging. A short message (e.g., "Invalid or empty input JSON") could help users quickly identify the issue.


67-70: Clarify default resolveReferences behavior.
Defaulting resolveReferences to 2 might be contextually correct, but consider a descriptive constant (e.g., const DEFAULT_RESOLVE_REFERENCES = 2) or inline comment to clarify its meaning.


102-125: Conflict filtering strategy is well-structured.
Thanks to dedicated methods (getInitialConflicts, getMergedCollection, validateNewAvailabilities, etc.), the conflict detection logic is simpler to follow. If users need more context when AvailabilityAddFailed is thrown, consider passing relevant info (e.g., conflict details) to the exception.


329-348: Extended update logic with $resolveReferences.
Allows for flexible entity resolution. For further clarity, unify your exception messages for missing entities (line 339) or add additional context to help identify which records failed.

zmsadmin/js/page/availabilityDay/helpers.js (2)

83-93: Time-rounding utility – roundToSlotBoundary.
Separating slot increments for 5 and 10 minutes is workable, though consider making the permissible increments more flexible for potential future changes (e.g., 15 minutes). Otherwise, good approach.


94-195: getNewAvailability robustly calculates default times.
You gather existing availabilities, calculate start/end times, and avoid overlaps. This is an elegant solution for auto-populating a new availability slot. Keep an eye on performance if the list of existing availabilities grows large; a more optimized search approach may eventually be needed.

zmsadmin/js/page/availabilityDay/form/validate.js (1)

30-30: Simplify the boolean assignment.

At line 30, the use of a ternary operator is unnecessary. You can directly assign a boolean by checking whether errorList.itemList.length is zero:

-  let valid = (0 < errorList.itemList.length) ? false : true;
+  let valid = (errorList.itemList.length === 0);
🧰 Tools
🪛 Biome (1.9.4)

[error] 30-30: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

zmsadmin/tests/Zmsadmin/AvailabilityConflictsTest.php (1)

1977-2485: Potential for data provider usage to reduce duplication.

Some test entries appear repetitively in multiple methods. Introducing dedicated data providers or fixture references might simplify maintenance and reduce code duplication in the future.

zmsadmin/js/page/availabilityDay/index.js (3)

153-153: Consider optional chaining.

Where you have:

(availability.tempId && availability.tempId.includes('__temp__'))

you could simplify with optional chaining if allowed:

- if (availability.tempId && availability.tempId.includes('__temp__')) {
+ if (availability.tempId?.includes('__temp__')) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 153-153: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


160-161: Avoid performance overhead from the delete operator.

The delete operator can introduce engine de-optimizations. Consider setting the property to undefined instead for better performance:

- delete sendAvailability.tempId;
+ sendAvailability.tempId = undefined;
🧰 Tools
🪛 Biome (1.9.4)

[error] 160-161: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


238-239: Apply the same fix for delete here as well.

Just like above, replace:

- delete sendAvailability.tempId;
+ sendAvailability.tempId = undefined;

to maintain consistency and avoid performance pitfalls.

🧰 Tools
🪛 Biome (1.9.4)

[error] 238-239: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

zmsentities/src/Zmsentities/Collection/AvailabilityList.php (3)

182-194: Aggregates validation from each Availability.

The merge approach is effective, but watch out for potential duplicates in $errorList if you plan to handle them distinctly.


341-370: checkForConflictsWithExistingAvailabilities.

Iterating day by day can be performance-intensive for large ranges. Possibly consider a more direct approach if performance becomes an issue.


372-417: findOverlapsOnDate.

Useful decomposition. The daily approach is simple to follow but might be suboptimal for extensive date ranges. Consider future improvements if needed.

zmsadmin/src/Zmsadmin/AvailabilityConflicts.php (1)

143-205: filterAndSortConflicts.

Groups conflicts by day, sorts them, and forms a new structure for the front end. This is a big chunk. Consider further extracting the day-group logic or adopting a specialized data structure.

zmsentities/src/Zmsentities/Availability.php (3)

116-116: Docblock type hint
The docblock suggests $type is always a string, but the code also accepts false. Consider updating the declaration to string|bool for accuracy.


141-141: Docblock type consistency
Same consideration as line 116: include bool in the docblock to reflect possible false values.


458-497: Potential code reuse
These time-of-day checks (22:00–01:00) may appear in other validation methods. Consider extracting common validation logic into a helper.

zmsadmin/routing.php (2)

24-25: AvailabilityDelete
Uses GET to delete availability. Typically, DELETE or POST would be more RESTful. Verify if this is intentional.


280-280: ProcessDelete
Again, uses GET to delete a resource. Consider changing it to POST or DELETE for consistency.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 09f57f6 and 7e98a91.

⛔ Files ignored due to path filters (1)
  • zmsadmin/src/Zmsadmin/debug.log is excluded by !**/*.log
📒 Files selected for processing (45)
  • zmsadmin/js/page/availabilityDay/form/conflicts.js (1 hunks)
  • zmsadmin/js/page/availabilityDay/form/content.js (5 hunks)
  • zmsadmin/js/page/availabilityDay/form/datepicker.js (10 hunks)
  • zmsadmin/js/page/availabilityDay/form/errors.js (2 hunks)
  • zmsadmin/js/page/availabilityDay/form/footerButtons.js (1 hunks)
  • zmsadmin/js/page/availabilityDay/form/formButtons.js (3 hunks)
  • zmsadmin/js/page/availabilityDay/form/index.js (2 hunks)
  • zmsadmin/js/page/availabilityDay/form/validate.js (5 hunks)
  • zmsadmin/js/page/availabilityDay/helpers.js (7 hunks)
  • zmsadmin/js/page/availabilityDay/index.js (21 hunks)
  • zmsadmin/js/page/availabilityDay/layouts/accordion.js (6 hunks)
  • zmsadmin/js/page/availabilityDay/layouts/page.js (2 hunks)
  • zmsadmin/js/page/availabilityDay/layouts/tableBody.js (5 hunks)
  • zmsadmin/js/page/availabilityDay/saveBar.js (1 hunks)
  • zmsadmin/js/page/availabilityDay/timetable/graphview.js (0 hunks)
  • zmsadmin/js/page/availabilityDay/timetable/index.js (1 hunks)
  • zmsadmin/js/page/availabilityDay/timetable/scopeview.js (1 hunks)
  • zmsadmin/routing.php (16 hunks)
  • zmsadmin/src/Zmsadmin/AvailabilityConflicts.php (3 hunks)
  • zmsadmin/src/Zmsadmin/AvailabilityListByScope.php (1 hunks)
  • zmsadmin/templates/exception/bo/zmsapi/exception/availability/availabilityaddfailed.twig (1 hunks)
  • zmsadmin/templates/exception/bo/zmsapi/exception/availability/availabilityupdatefailed.twig (1 hunks)
  • zmsadmin/templates/page/availabilityday.twig (1 hunks)
  • zmsadmin/tests/Zmsadmin/AvailabilityConflictsTest.php (6 hunks)
  • zmsadmin/tests/Zmsadmin/fixtures/GET_Workstation_Resolved2.json (1 hunks)
  • zmsadmin/tests/Zmsadmin/fixtures/GET_Workstation_scope_141_multipleSlotsEnabled.json (1 hunks)
  • zmsadmin/tests/Zmsadmin/fixtures/GET_scope_141.json (1 hunks)
  • zmsadmin/tests/Zmsadmin/fixtures/GET_scope_141_multipleSlotsEnabled.json (1 hunks)
  • zmsadmin/tests/Zmsadmin/fixtures/GET_scope_list.json (1 hunks)
  • zmsapi/src/Zmsapi/AvailabilityAdd.php (1 hunks)
  • zmsapi/src/Zmsapi/AvailabilityUpdate.php (1 hunks)
  • zmsapi/src/Zmsapi/Exception/Availability/AvailabilityAddFailed.php (1 hunks)
  • zmsapi/src/Zmsapi/Exception/Availability/AvailabilityUpdateFailed.php (1 hunks)
  • zmsapi/tests/Zmsapi/AvailabilityAddTest.php (2 hunks)
  • zmsapi/tests/Zmsapi/AvailabilityUpdateTest.php (3 hunks)
  • zmsdb/src/Zmsdb/Process.php (1 hunks)
  • zmsdb/tests/Zmsdb/AvailabilityTest.php (1 hunks)
  • zmsdb/tests/Zmsdb/ProcessConflictTest.php (3 hunks)
  • zmsentities/schema/availability.json (2 hunks)
  • zmsentities/schema/dereferenced/appointment.json (1 hunks)
  • zmsentities/schema/dereferenced/availability.json (1 hunks)
  • zmsentities/src/Zmsentities/Availability.php (11 hunks)
  • zmsentities/src/Zmsentities/Collection/AvailabilityList.php (5 hunks)
  • zmsentities/tests/Zmsentities/AvailabilityTest.php (8 hunks)
  • zmsentities/tests/Zmsentities/ProcessTest.php (1 hunks)
💤 Files with no reviewable changes (1)
  • zmsadmin/js/page/availabilityDay/timetable/graphview.js
✅ Files skipped from review due to trivial changes (4)
  • zmsadmin/templates/exception/bo/zmsapi/exception/availability/availabilityaddfailed.twig
  • zmsadmin/templates/exception/bo/zmsapi/exception/availability/availabilityupdatefailed.twig
  • zmsadmin/templates/page/availabilityday.twig
  • zmsapi/src/Zmsapi/Exception/Availability/AvailabilityUpdateFailed.php
🧰 Additional context used
📓 Path-based instructions (2)
`**/*.php`: Flag any usage of error_log() as it should be re...

**/*.php: Flag any usage of error_log() as it should be replaced with proper logging mechanisms:

  1. For error handling: Use a proper logging framework with error levels (PSR-3 LoggerInterface)
  2. For debugging: Use a dedicated debug logger or remove debug statements
  3. For CLI output: Use a CLI output handler or symfony/console
  4. For application events: Use structured logging with proper log levels

Example replacement:

// Instead of:
error_log("Import failed - " . $e->getMessage());

// Use:
$logger->error("Import failed", ['error' => $e->getMessage()]);
  • zmsdb/tests/Zmsdb/AvailabilityTest.php
  • zmsapi/src/Zmsapi/Exception/Availability/AvailabilityAddFailed.php
  • zmsdb/src/Zmsdb/Process.php
  • zmsdb/tests/Zmsdb/ProcessConflictTest.php
  • zmsadmin/src/Zmsadmin/AvailabilityListByScope.php
  • zmsapi/tests/Zmsapi/AvailabilityAddTest.php
  • zmsentities/tests/Zmsentities/ProcessTest.php
  • zmsentities/src/Zmsentities/Collection/AvailabilityList.php
  • zmsapi/tests/Zmsapi/AvailabilityUpdateTest.php
  • zmsadmin/src/Zmsadmin/AvailabilityConflicts.php
  • zmsentities/src/Zmsentities/Availability.php
  • zmsentities/tests/Zmsentities/AvailabilityTest.php
  • zmsapi/src/Zmsapi/AvailabilityAdd.php
  • zmsapi/src/Zmsapi/AvailabilityUpdate.php
  • zmsadmin/tests/Zmsadmin/AvailabilityConflictsTest.php
  • zmsadmin/routing.php
`**/*.{js,jsx,ts,tsx}`: Flag any usage of console.log() as i...

**/*.{js,jsx,ts,tsx}: Flag any usage of console.log() as it should be replaced with proper logging:

  1. For development: Use proper debug tools or logging libraries
  2. For production: Remove console.log() statements or use structured logging
  3. For errors: Use error tracking services (e.g., Sentry)
  4. For debugging: Consider using debug libraries that can be enabled/disabled

Example replacement:

// Instead of:
console.log('User data:', userData);

// Use:
logger.debug('Processing user data', { userData });
// or for development only:
if (process.env.NODE_ENV === 'development') {
  debug('User data:', userData);
}
  • zmsadmin/js/page/availabilityDay/timetable/index.js
  • zmsadmin/js/page/availabilityDay/layouts/page.js
  • zmsadmin/js/page/availabilityDay/form/index.js
  • zmsadmin/js/page/availabilityDay/form/errors.js
  • zmsadmin/js/page/availabilityDay/timetable/scopeview.js
  • zmsadmin/js/page/availabilityDay/form/conflicts.js
  • zmsadmin/js/page/availabilityDay/form/content.js
  • zmsadmin/js/page/availabilityDay/layouts/accordion.js
  • zmsadmin/js/page/availabilityDay/layouts/tableBody.js
  • zmsadmin/js/page/availabilityDay/form/footerButtons.js
  • zmsadmin/js/page/availabilityDay/form/datepicker.js
  • zmsadmin/js/page/availabilityDay/form/formButtons.js
  • zmsadmin/js/page/availabilityDay/helpers.js
  • zmsadmin/js/page/availabilityDay/index.js
  • zmsadmin/js/page/availabilityDay/form/validate.js
  • zmsadmin/js/page/availabilityDay/saveBar.js
🧠 Learnings (4)
zmsadmin/js/page/availabilityDay/layouts/page.js (1)
Learnt from: ThomasAFink
PR: it-at-m/eappointment#685
File: zmsadmin/js/page/availabilityDay/layouts/page.js:14-14
Timestamp: 2024-12-04T12:18:56.123Z
Learning: In `zmsadmin/js/page/availabilityDay/layouts/page.js`, it's acceptable to render the `saveBar` component twice, once after `props.timeTable` and once after `props.accordion`, to display the save bar at both the top and bottom of the layout.
zmsadmin/js/page/availabilityDay/index.js (2)
Learnt from: ThomasAFink
PR: it-at-m/eappointment#0
File: :0-0
Timestamp: 2025-01-30T15:35:15.938Z
Learning: In the eappointment system's handleChange method, when validating form changes, run getValidationList and getConflictList in parallel using Promise.all, and only proceed with readCalculatedAvailabilityList after both validations complete to avoid race conditions.
Learnt from: ThomasAFink
PR: it-at-m/eappointment#0
File: :0-0
Timestamp: 2025-01-27T16:54:44.665Z
Learning: In the eappointment system's getConflictList method, create a copy of selectedAvailability before modifying it to avoid mutating state directly, handle null selectedAvailability gracefully, clear stale conflicts on errors, and maintain a consistent promise chain to ensure proper button state management.
zmsadmin/src/Zmsadmin/AvailabilityConflicts.php (3)
Learnt from: ThomasAFink
PR: it-at-m/eappointment#0
File: :0-0
Timestamp: 2025-02-17T09:47:44.330Z
Learning: The getAvailabilityData() method in AvailabilityConflicts.php should be refactored into smaller methods: validateInput(), processAvailabilityKinds(), getConflictList(), and filterAndSortConflicts() to improve maintainability and reduce complexity.
Learnt from: ThomasAFink
PR: it-at-m/eappointment#0
File: :0-0
Timestamp: 2025-02-17T09:49:29.414Z
Learning: The getAvailabilityData() method in AvailabilityConflicts.php should be refactored to reduce complexity by:
1. Extracting validation logic into separate methods
2. Breaking down availability kind processing
3. Isolating conflict filtering logic
4. Moving sorting to dedicated methods
5. Using early returns to avoid nested conditions
Learnt from: ThomasAFink
PR: it-at-m/eappointment#0
File: :0-0
Timestamp: 2025-02-17T09:44:29.822Z
Learning: The `getAvailabilityData` method in `AvailabilityConflicts` class should be refactored to reduce complexity by:
1. Extracting validation logic into separate methods
2. Breaking down availability kind processing
3. Isolating conflict filtering logic
4. Moving sorting to dedicated methods
5. Using early returns to avoid nested conditions
zmsapi/src/Zmsapi/AvailabilityAdd.php (2)
Learnt from: ThomasAFink
PR: it-at-m/eappointment#0
File: :0-0
Timestamp: 2025-02-17T10:13:48.667Z
Learning: The readResponse() method in AvailabilityAdd.php should be refactored to reduce complexity by:
1. Separating input validation into dedicated methods
2. Breaking down collection processing logic
3. Isolating conflict detection and filtering
4. Moving entity update logic to separate methods
5. Using type hints for better code clarity
Learnt from: ThomasAFink
PR: it-at-m/eappointment#0
File: :0-0
Timestamp: 2025-02-17T10:19:41.023Z
Learning: The readResponse() method in AvailabilityUpdate.php should be refactored to reduce complexity by:
1. Separating input validation into dedicated methods
2. Breaking down collection processing logic
3. Isolating conflict detection and filtering
4. Moving entity update logic to separate methods
5. Using type hints for better code clarity
🪛 Biome (1.9.4)
zmsadmin/js/page/availabilityDay/form/index.js

[error] 46-50: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

zmsadmin/js/page/availabilityDay/form/conflicts.js

[error] 33-33: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

zmsadmin/js/page/availabilityDay/form/content.js

[error] 24-24: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

zmsadmin/js/page/availabilityDay/layouts/accordion.js

[error] 172-172: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

zmsadmin/js/page/availabilityDay/layouts/tableBody.js

[error] 38-38: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 39-39: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 43-43: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 44-44: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 57-57: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 58-58: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 65-65: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 66-66: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 70-70: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 71-71: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 214-214: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

zmsadmin/js/page/availabilityDay/index.js

[error] 153-153: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 160-161: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)


[error] 238-239: Avoid the delete operator which can impact performance.

Unsafe fix: Use an undefined assignment instead.

(lint/performance/noDelete)

zmsadmin/js/page/availabilityDay/form/validate.js

[error] 30-30: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

🔇 Additional comments (222)
zmsadmin/js/page/availabilityDay/timetable/index.js (1)

1-37: File structure change detected

According to the summary, the renderFooter function has been removed from this file. This aligns with changes in related components that no longer use footer elements. This simplification is a positive change that streamlines the UI.

zmsadmin/tests/Zmsadmin/fixtures/GET_Workstation_Resolved2.json (1)

153-153: Update Slot Duration in Workstation Fixture
The slotTimeInMinutes field is updated to 10, which aligns with the new appointment slot duration requirements. Please double-check that this change is consistent with the updated schema and other related fixtures.

zmsadmin/tests/Zmsadmin/fixtures/GET_scope_141.json (1)

100-100: Consistent Slot Duration Update in Scope Fixture
The provider’s slotTimeInMinutes is now set to 10. This change should ensure consistency in appointment scheduling logic across the system. Verify that downstream validations and schema definitions are updated correspondingly.

zmsadmin/tests/Zmsadmin/fixtures/GET_Workstation_scope_141_multipleSlotsEnabled.json (1)

152-156: Slot Duration and Multiple Slots Fixture Validation
The provider’s slotTimeInMinutes is updated to 10 in this fixture. In addition, please confirm that the multipleSlotsEnabled setting remains accurate for validating scenarios that allow multiple appointment slots.

zmsadmin/tests/Zmsadmin/fixtures/GET_scope_list.json (1)

101-102: Standardizing Slot Duration in Scope List Fixture
The update to "slotTimeInMinutes": 10 aligns this fixture with the new duration standard. Ensure that all components relying on this value are consistent with the change.

zmsadmin/tests/Zmsadmin/fixtures/GET_scope_141_multipleSlotsEnabled.json (1)

100-104: Standardizing Slot Duration in Multiple Slots Scope Fixture
The provider’s slotTimeInMinutes is now set to 10, matching the changes across other fixtures. Please ensure that the test scenarios covering multiple slots are still valid with this updated duration.

zmsapi/src/Zmsapi/Exception/Availability/AvailabilityAddFailed.php (1)

8-13: Implementation looks good

The exception class is properly defined with the appropriate error code (400) for client error and a clear error message that provides guidance to the user.

zmsentities/schema/dereferenced/availability.json (1)

21-21:

✅ Verification successful

Slot time adjustment affects appointment duration calculations

The change from 12 to 10 minutes for slotTimeInMinutes will reduce the time allocated per slot by 2 minutes. This has implications for appointment durations since this value is multiplied by the slotCount to determine total appointment duration.


🏁 Script executed:

#!/bin/bash
# Verify that all references to slotTimeInMinutes have been updated consistently
echo "Checking for any other slotTimeInMinutes references that may need to be updated:"
rg -l "slotTimeInMinutes.*12" --type json

Length of output: 214


Confirmation: Slot Time Update Validated

The update changing slotTimeInMinutes from 12 to 10 appears to be consistently applied. The verification command did not return any JSON files with a lingering value of 12, indicating that all relevant references have been updated. This 2‑minute reduction per slot will naturally affect appointment duration calculations (since the slot count is multiplied by this value), so please ensure that any downstream business logic correctly reflects this new timing.

zmsdb/tests/Zmsdb/AvailabilityTest.php (1)

77-77: Test assertion correctly updated to match new slot time

The test has been properly updated to assert the new expected value of 10 for slotTimeInMinutes, which aligns with the schema changes.

zmsentities/schema/dereferenced/appointment.json (2)

38-38: Example value correctly updated for consistency

The example value for slotTimeInMinutes has been correctly updated to 10, maintaining consistency with the availability schema change.


129-133: Default value consistency verified

The default value in the property definition (line 131) already shows 10, which aligns with the updated example value. Good to see both values are consistent.

zmsdb/src/Zmsdb/Process.php (1)

495-495: Method name change enhances conflict checking specificity.

The method call has been updated from getConflicts to the more descriptive checkForConflictsWithExistingAvailabilities, which better reflects its specific purpose of validating against existing availability entries.

zmsentities/tests/Zmsentities/ProcessTest.php (1)

494-494: Test expectation updated to reflect new slot time duration.

The expected end time has been changed from '19:16' to '19:12', which aligns with the updated slot time from 12 minutes to 10 minutes defined in the schema. This ensures the test remains valid with the new time calculations.

zmsadmin/js/page/availabilityDay/form/index.js (3)

6-6: Import of slot count validation function enhances error handling.

The addition of the hasSlotCountError import adds specific slot count validation capability to the form component.


41-44: Improved formatting for readability.

The conditional logic has been reformatted for better readability while maintaining the same functionality.

🧰 Tools
🪛 Biome (1.9.4)

[error] 41-44: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


70-71: Enhanced error state propagation to form buttons.

The form now passes error state information to the FormButtons component, allowing the UI to better reflect validation status and prevent form submission when errors exist.

zmsentities/schema/availability.json (2)

21-21: Slot time duration adjustment from 12 to 10 minutes.

The slot time duration has been reduced from 12 to 10 minutes, which will affect how appointment durations are calculated throughout the system.

This change will impact appointment scheduling and availability calculations system-wide. Please ensure all dependent UI components and calculations have been updated to reflect this time change.


122-125: Addition of 'kind' property enhances availability categorization.

The new 'kind' property allows for more flexible categorization of availabilities beyond the existing 'type' property.

Consider documenting the expected values for the 'kind' property, possibly with an enum of allowed values, to ensure consistent usage across the application.

zmsadmin/js/page/availabilityDay/layouts/page.js (2)

14-14: LGTM: Added saveBar at the bottom.

The addition of the saveBar at the bottom of the layout improves user experience by making the save functionality accessible without requiring scrolling back to the top.


23-23: LGTM: Updated PropTypes.

The PropTypes definition has been correctly updated to include the saveBar property.

zmsadmin/js/page/availabilityDay/form/conflicts.js (1)

14-26: Improved conflict aggregation logic.

The implementation now correctly groups conflicts by message and associates multiple dates with each conflict message, making the UI more organized.

zmsadmin/js/page/availabilityDay/form/errors.js (3)

1-2: LGTM: Consistent semicolons.

Added semicolons to maintain code consistency.


4-17: Enhanced error handling for nested arrays.

The implementation now correctly handles both simple error messages and nested arrays of error messages, making the error display more robust.


26-27: LGTM: Consistent semicolons.

Added semicolons to maintain code consistency.

Also applies to: 31-31, 35-35, 37-37

zmsdb/tests/Zmsdb/ProcessConflictTest.php (2)

103-105: LGTM: Improved conflict message detail.

The test now checks for a more detailed conflict message that includes specific information about the conflicting time slots, which aligns with the PR objective of improving validation messaging.


120-122: LGTM: Improved conflict message detail.

The test now checks for a more detailed conflict message for overlapping opening hours, which provides clearer feedback to users.

zmsadmin/js/page/availabilityDay/timetable/scopeview.js (1)

1-48: Clean, well-structured new component - looks good!

The ScopeView component is well-implemented using functional React style, with proper prop validation, clear organization, and good separation of concerns.

zmsadmin/js/page/availabilityDay/layouts/accordion.js (2)

28-31: Good implementation for checking new or temporary availabilities

The check for temporary IDs and exclusion kinds is a clean approach to determine if there are new availabilities in the list.


173-177: Good error handling logic for past time errors

The code now properly filters out endTimePast errors when determining if there are validation errors that should block form submission.

zmsadmin/js/page/availabilityDay/form/formButtons.js (3)

20-21: Good validation with date checking

Adding the isPastDate check and incorporating new validation flags (hasErrors, hasSlotCountError) enhances form validation.


38-38: Comprehensive disabled logic for exception button

The disabled state now properly accounts for multiple scenarios including past dates, end dates matching selected dates, and creation state.


49-57: Well-structured conditions for update button

The clearly formatted multi-line conditions for the "Aktualisieren" button make the logic easy to read and maintain.

zmsadmin/js/page/availabilityDay/layouts/tableBody.js (1)

9-28: Well-implemented sorting with React hooks

The sortColumn/sortDirection state management and toggleable sorting direction provide a good user experience.

zmsadmin/js/page/availabilityDay/form/content.js (4)

21-25: Consider simplifying conditional logic and verifying usage of calenderDisabled.
hasEndTimePastError is derived from a nested .some(...) check, and calenderDisabled is set based on slotTime/type presence. The resulting inputDisabled is correct for disabling the form when needed. However, ensure that the naming calenderDisabled is intentional and that this logic fully addresses all user scenarios where form inputs must be locked.

🧰 Tools
🪛 Biome (1.9.4)

[error] 24-24: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


29-34: Filtered error logic looks good.
Filtering out the endTimePast errors helps separate them from the general error display in ErrorBar. This improves clarity and is a neat approach.


70-105: Check for consistency when handling multiple endTimePast errors.
Currently, only the first array element is checked before returning, and multiple items could exist in error.itemList. This may be sufficient for your use case, but confirm that additional items wouldn’t need to be displayed.


236-299:

❓ Verification inconclusive

Verify the usage of range(0, data.workstationCount_intern).
If you intend to allow a count that includes data.workstationCount_intern itself, note that range(0, n) yields [0 ... n-1]. If your goal is [0 ... n], consider using range(0, data.workstationCount_intern + 1).


🏁 Script executed:

#!/bin/bash
# Scans the 'form/content.js' references to confirm how 'workstationCount_intern' is used.
rg -A 5 'workstationCount_intern'

Length of output: 5558


Verify the off-by-one behavior for workstation selection options
In file zmsadmin/js/page/availabilityDay/form/content.js (lines 236–299), the select control options for “Callcenter” and “Internet” are generated using range(0, data.workstationCount_intern). This code produces values from 0 up to data.workstationCount_intern - 1, which means the maximum option is one less than the numeric value in data.workstationCount_intern. If the intended behavior is to allow a selection up to and including the full count (i.e. [0 … data.workstationCount_intern]), the range should be updated to range(0, data.workstationCount_intern + 1). Please verify whether this adjustment is needed based on the intended UX and business logic.

zmsadmin/js/page/availabilityDay/saveBar.js (1)

13-21: Visibility timer logic is appropriate.
Using a useEffect hook with a timeout is a straightforward way to hide the save bar after a specified interval. The cleanup returning clearTimeout(timer) is correct.

zmsapi/tests/Zmsapi/AvailabilityUpdateTest.php (3)

16-49: Future date logic looks correct.
Using time() + (N * 24 * 60 * 60) ensures the availability starts days in the future. This chunk comprehensively builds the required input.


128-128: Great usage of expectException(AvailabilityUpdateFailed::class).
This clarifies precisely which exception the test should raise for invalid end times.


177-192: JSON-based error response is consistently tested.
Adding a JSON body in testNotFound() ensures uniform validation of the response. This is consistent with the earlier test structure.

zmsadmin/src/Zmsadmin/AvailabilityListByScope.php (1)

28-30: Good parameter check for 'id'.
This ensures that missing scope IDs are caught early, promoting more robust request handling.

zmsadmin/js/page/availabilityDay/form/footerButtons.js (1)

43-43: Verify time zone handling for isPastDate.
isPastDate compares only the date portion. If exact times or different time zones matter, consider whether you need additional checks (e.g., accounting for UTC offsets).

zmsadmin/js/page/availabilityDay/form/datepicker.js (2)

125-133: Verify missing boundary times in the maintenance window.
The loop excludes minute=0 for 22:00 and minute=59 for 00:59, leaving gaps (22:00, 00:59) not explicitly handled. Confirm whether this is intentional or should be included in the exclusion.


308-321: Confirm consistency between filterPassedTime and maintenance window logic.
While filterPassedTime blocks 22:00-01:00, getMaintenanceWindowTimes() omits specific minutes. Double-check both approaches align with the same maintenance rules to avoid confusion.

zmsapi/src/Zmsapi/AvailabilityAdd.php (18)

20-20: No issues introducing the new exception class import.


33-41: Refactored readResponse method is on the right track.
You've successfully delegated core logic to helper methods (validateAndGetInput, processAvailabilityAddition, generateResponse). This aligns with the retrieved learnings about reducing complexity. Consider documenting the rationale behind acquiring the write DB connection here (line 36) so future maintainers can quickly understand its necessity.


54-65: Validation approach looks solid.
The structure checks for availabilityList and selectedDate significantly reduce the chance of passing malformed data deeper into the system. Consider adding or unifying error messages to provide consistent debugging clues (e.g., “Missing availabilityList” vs. “Missing or invalid scope”).


72-81: Efficient breakdown of availability addition flow.
This method nicely encapsulates the creation of a new collection, date resolution, conflict checks, and final updates. Keeping responsibilities separate in dedicated methods (e.g., createSelectedDateTime(), validateAndCheckConflicts()) supports maintainability.


83-92: Proper entity instantiation and validation.
Creating the new collection and calling $entity->testValid() early on ensures only valid entities progress. Good practice for robust domain modeling.


94-101: Check for invalid date strings.
createFromFormat returns false on failure, though it’s unlikely in normal usage. If user input can be malformed, consider gracefully handling or logging parse errors.


127-133: Initial conflict detection is straightforward.
The method efficiently collects intra-collection conflicts, which is good. Ensure that subsequent calls or expansions of conflict checks remain consistent.


135-145: Repository usage is appropriate here.
Merging the existing availabilities from DB with new ones is logically sound. Consider clarifying whether the repository might throw exceptions on DB issues, and if so, handle them (e.g., logging or rethrow).


147-164: Incremental validation approach is effective.
Each new availability merges into the collection and is validated incrementally, preventing partial conflicts from proceeding. Clear error messaging at the point of failure would further aid debugging but otherwise, this is strong.


166-189: Time-based calculations done carefully.
You properly convert timestamps to DateTimeImmutable objects and combine them with startTime/endTime. If time zones are a concern in production, ensuring these are aware or consistent would be important.


191-202: Selective filtering logic is concise.
Extracting only relevant availabilities based on originId fosters clarity. No issues spotted.


204-216: Efficient search for origin kind.
Straightforward iteration to find the relevant ID. Looks good.


218-222: Simplicity in including or excluding entities.
This conditional is easy to read and maintain.


224-236: Extended conflict checks.
Your approach is methodical: after merging, you collect any new conflicts from the existing set. This ensures thorough coverage of potential overlaps.


238-258: Weekday-based conflict filtering is logical.
The code is well-partitioned, focusing on the narrower logic of weekday collisions. Nicely done.


260-311: Transactional safety consideration.
While updateEntities iterates over each entity, be mindful: if one fails, do the others roll back? Depending on your DB layer, partial updates may occur. If full atomicity is desired, consider wrapping these updates in a transaction.


313-327: Consistent response generation.
Using Render::withJson and setUpdatedMetaData() helps unify response formatting. This is clear and maintainable.


353-360: Spontaneous entity adjustments are well-encapsulated.
Resetting certain fields before rewriting ensures the correct state. If these fields need to be tracked or audited, remember to log relevant changes.

zmsapi/tests/Zmsapi/AvailabilityAddTest.php (6)

5-6: New import for AvailabilityAddFailed is fine.
Nothing else to note here.


14-56: testRendering updates.
You now generate a more detailed request JSON with weekday, dayoff, and date/time calculations. This test ensures the addition logic handles real-world-like data. Good coverage.


62-119: testOverlappingAvailability scenario coverage.
Testing multiple overlapping entries ensures correct conflict detection. This is essential for verifying the new conflict logic in AvailabilityAdd.


121-178: Robust duplication checks in testDuplicateOverlappingAvailability.
Identifies repeated availability inserts that ought to raise a conflict. Demonstrates thorough coverage of conflict detection.


180-201: testInvalidEndTime ensures correct time validation.
Good approach to confirm that end times before start times throw AvailabilityAddFailed. These negative tests are crucial for data integrity.


220-239: Refined testAddFailed.
Switched from AvailabilityUpdateFailed to AvailabilityAddFailed to align with new backend error handling. This is consistent with changes in AvailabilityAdd logic.

zmsadmin/js/page/availabilityDay/helpers.js (4)

3-18: getStateFromProps enhancements.
Accepting existingState fosters state reusability. The additional properties (saveType, lastSave, saveSuccess) are helpful for preserving user flow status; no issues noted.


43-55: updateAvailabilityInState: tracking stateChanged.
Setting stateChanged to true upon any modification is a neat clarity improvement to reflect changes in UI or data. Implementation looks solid.


260-266: getDataValuesFromForm: using appointment defaults.
Lines 265–266 demonstrate fallback behavior if fields are empty. This is valuable for user-friendly forms.


283-294: cleanupFormData refines user input.
Stripping out default or unchanged fields helps keep the final payload clean. This can mitigate potential over-posting or extraneous data issues.

zmsadmin/js/page/availabilityDay/form/validate.js (3)

38-104: Looks clean and well-organized.

The validateWeekdays function provides thorough checks for required weekdays and ensures that chosen weekdays exist within the specified date range. This is a tidy and robust approach to weekday validation.


229-274: Good handling of restricted hours logic.

The conditional checks for disallowing times between 22:00 and 01:00 are clearly defined and well-structured. The error message is also informative and helpful for users.


345-363: Nice modular approach to validating slot times.

The validateSlotTime function efficiently checks that the total minutes in the availability window is divisible by the slot length. This modular design keeps the validation logic clean and maintainable.

zmsadmin/tests/Zmsadmin/AvailabilityConflictsTest.php (1)

13-1975: Increased test coverage is commendable.

The expanded test methods (e.g., testDifferentWeekdaysConflict, testMultipleConflicts, etc.) thoroughly verify various scenarios. This significantly enhances confidence in the availability conflict logic.

zmsadmin/js/page/availabilityDay/index.js (1)

116-130: Smart consolidation of state updates.

Your updateDataState method neatly centralizes updates to conflicts and availability lists, simplifying the refresh flow. This approach boosts maintainability.

zmsentities/tests/Zmsentities/AvailabilityTest.php (35)

182-182: Verify updated available seconds calculation.

You're asserting 6534000 instead of the former value. Double-check that the underlying logic or constants accurately produce this new expected value.


199-199: Double-check correctness of new expected seconds.

Ensure that 6534000 aligns with the latest computation rules in getAvailableSecondsOnDateTime().


501-501: Validate the workstation count change.

You've updated the public workstation count assertion to 99. Confirm that this aligns with the updated logic in withCalculatedSlots().


509-509: Confirm increased slot count.

The new expected count is 33. Verify that the underlying changes (e.g., slot length, offsets) justify this increase from the previous value.


511-511: Check new slot time value.

Changing '10:12' to '10:10' might indicate a 10-minute increment approach. If that’s correct as per new specifications, this is good.


543-543: Dynamic check of entity count.

Using count($collection) in the message is a nice improvement for debugging.


552-552: Validate updated workstation count in collection.

It’s now 99. Confirm it matches business rules for seat calculations.


869-869: Confirm usage of identical start and end dates.

Calling checkForConflictsWithExistingAvailabilities with the same date as start and end might restrict the conflict check to a single day. Ensure that is intended.


873-873: LGTM on conflict indexing.

Using if (!isset($list[$conflict->amendment])) is a clear approach for grouping conflicts by message.


876-876: Check nested array existence.

Your nested if (!isset($list[$conflict->amendment][$id])) is logically consistent for building conflict sub-lists. Looks good.


883-901: Overlapping availability checks look good.

The assertions verify that Availabilities (1 and 5, 2 and 4) properly detect collisions; logic is explicit and well-labeled.


902-920: Exact-match conflict assertions are clear.

Nice usage of distinct messages for exact matches vs. overlaps; helps differentiate test scenarios.


951-1007: Partial overlap testing is thorough.

Covers start, end, and contained overlaps. This is a solid addition to ensure correctness.


1009-1053: Edge cases handled.

Back-to-back slots and crossing midnight are well tested without false positives.


1055-1101: Weekday overlap checks.

Verifying different repeating intervals for the same weekday is valuable. Good coverage.


1142-1166: Start time validation.

Ensures future/past logic is handled. These tests improve confidence in scheduling rules.


1167-1187: End time validation.

Identifies backward times or invalid ranges. Straightforward and correct.


1189-1208: Origin end time checks.

Properly tests scenarios with day offsets and reuses the 'origin' vs 'current' flags.


1210-1220: Type validation logic.

Confirms that an empty string is invalid and recognized types pass. Solid coverage.


1222-1241: Slot time validation.

Covers zero, partial divisibility, and normal intervals, ensuring correct error flags.


1243-1253: Bookable day range.

Verifies that start and end day values are consistent. Good negative and positive checks.


1255-1291: Maintenance window compliance.

Ensures that overnight times or large offsets trigger the correct rules.


1293-1317: Future date start time checks.

Confirms that scheduling in the future is recognized under the right contexts.


1319-1333: Minute-precision end time.

Guards against identical start/end edge conditions. Good detail.


1335-1354: Slot time divisibility.

Ensures that total time must be an integer multiple of the slot length. Good boundary tests.


1356-1369: Bookable day range order.

Checks negative or zero ranges, ensuring no accidental misconfiguration.


1371-1384: Allowed type values.

Ensures recognized strings like 'appointment', 'openinghours' etc. pass.


1386-1419: Summarized slot counts.

Correctly validates multiple availabilities with 10-min increments.


1421-1438: Default values verified.

Confirms that new Availability objects have correct initial fields (slotTimeInMinutes, type, etc.).


1440-1471: Entity matching checks.

testIsMatchOf thoroughly tests partial differences in type, time, or weekday. Good coverage.


1473-1497: Cache clearing test.

Ensures dynamic changes to times are re-evaluated. Implementation is correct.


1499-1519: Edge-case time checks.

Verifies boundary conditions for start/end times. This is important for accurate scheduling.


1521-1537: Per-type available seconds.

Validates the multiplied seconds logic for each workstation type. Looks correct.


1539-1587: No conflicts on days of inactivity.

Ensures the system properly ignores mismatched weekdays. Good approach.


1589-1640: Conflicts on active weekday.

Ensures overlapping Tuesday availabilities produce conflict results. Good final coverage.

zmsentities/src/Zmsentities/Collection/AvailabilityList.php (10)

10-10: Dependency import seems appropriate.

Using ProcessList is consistent with your conflict management features below.


23-23: Changed reference to 'workstationCount'['intern'].

Ensure no regression if the maximum was previously determined by a different key.


166-174: New method: validateInputs.

Centrally validating date ranges and booking constraints is a good pattern. Well done.


196-216: Function getDateTimeRangeFromList.

Cleanly extracts min start and max end from the list. This is a helpful utility for broad date computations.


228-228: Method signature update: getCalculatedSlotCount.

Now accepts ProcessList untyped from a FQCN. Works well if consistent across the codebase.


258-311: checkForConflictsBetweenNewAvailabilities.

Compares newly provided entries for overlaps or equality. A valuable addition for local conflict detection.


313-339: createConflictMessage.

Clearer conflict string generation. This method fosters consistent, localized message construction.


419-449: shouldCompareForConflicts.

Good checks for type, scope, and ID to filter out unneeded comparisons. This approach avoids false conflict flags.


451-472: doAvailabilitiesOverlap.

Straightforward date/time overlap logic. If expansions or partial-day logic changes in the future, keep clarity in mind.


474-484: areAvailabilityTimesEqual.

Helps differentiate exact match from mere overlap. Fine approach.

zmsadmin/src/Zmsadmin/AvailabilityConflicts.php (11)

5-5: Imported BadRequest for exceptions.

Ensures consistent error handling naming. Looks correct.


7-9: Added ProcessList, Scope, and DateTimeImmutable imports.

These are necessary dependencies for conflict logic. Good usage.


13-14: New conflict type constants.

Defines 'equal' and 'overlap' for clarity. They might be extended if new conflict categories appear.


23-24: Revised JSON response invocation.

Using \BO\Slim\Render::withJson to output final data is consistent with the rest of the project.


29-30: validateInput method extracted.

Good step toward decoupling input checks from main logic, improving readability.


31-60: Input checks.

Enforces the presence of availabilityList, scope, and selectedDate. This clarifies error reporting early.


62-79: processAvailabilityKinds method.

Detecting whether we have origin/exclusion/future availabilities ensures the correct conflict checks later.


81-114: getConflictList.

Nicely delegates to checkForConflictsBetweenNewAvailabilities and checkForConflictsWithExistingAvailabilities. This is more modular.


116-141: getFilteredAvailabilityList.

Excludes origin availability if there's an exclusion split. Straightforward approach to prepare final conflict checks.


207-220: addToConflictedList method.

Prevents duplicates and tracks both availability references. This method is short and readable.


222-235: sortConflictedList method.

The logic to push temporary IDs to the end is helpful for ordering new items distinctly. Nicely done.

zmsentities/src/Zmsentities/Availability.php (15)

252-253: Potential side-effect from modify()
Calling modify($monday) on both $dateTime and $start changes these objects in place, which may cause unexpected behavior if they are used elsewhere. Clone them if you need to preserve the original state.


284-284: Using 'today' token
Using 'today ' . $this['startTime'] is an acceptable approach for reset and adjustment in PHP's date engine.


299-299: Consistent approach for end time
Mirrors the logic used for the start time with 'today'. No issues observed.


313-313: Returning day difference
Casting the result of diff(...)->format("%a") to an int discards partial days, which appears intentional.


442-442: In-place date modification
$startTime->modify('+1 day') alters $startTime. Ensure the caller does not rely on its pre-modification value.


499-525: End time validation
Ensures end time is not before the start time or date. Straightforward check—good job.


527-553: Handling 'origin' vs. 'future'
These checks ensure that end times align with the specified kind. Confirm logic correctness with realistic test cases.


555-565: Type check
Properly ensures $kind is set. This block is minimal but effective.


567-597: Validating slot times
Prevents a slot time of zero and ensures the total minutes are divisible by this slot length. Looks good.


599-610: Bookable day range
Verifies startInDays is not greater than endInDays. Straightforward validation.


649-655: Weekday comparison in isMatchOf
Casting weekday values to bool and comparing them is a concise way to check matches. Implementation seems correct.


662-669: Logic check in hasSharedWeekdayWith
The condition implies a && on all weekday differences, which might invert the intended meaning. Confirm that this logic is correct.


672-737: validateWeekdays method
Ensures at least one weekday is selected and checks that each chosen weekday occurs within the given date range. Nicely done.


852-871: getWeekdayNames
Generates localized weekday names for the selected days. Straightforward approach.


963-984: Selective data removal
Conditionally unsetting keys based on keepArray is an efficient way to trim entity data. Works as intended.

zmsapi/src/Zmsapi/AvailabilityUpdate.php (26)

10-12: Newly imported classes
Bringing in AvailabilityList, ProcessList, and Scope clarifies usage and keeps the code organized.


16-18: Exception classes
Centralizes error handling with custom exception classes. Good practice.


29-36: Refined readResponse method
Retrieves validated input, obtains references, and calls the main processing logic in a concise manner.


39-49: validateAndGetInput()
Checks for JSON input and throws a BadRequestException if empty. Solid approach.


50-61: validateInputStructure()
Validates the presence of availabilityList, scope information, and a selectedDate. Robust checks.


63-66: getResolveReferences()
Retrieves a numeric parameter with a default of 2. Straightforward design choice.


68-77: processAvailabilityUpdate()
Core orchestration: validates data, checks conflicts, and updates entities. Nicely modularized.


79-96: createAndValidateCollection()
Constructs a collection of new entities from user input and validates them. Good separation of concerns.


98-105: validateExistingEntity()
Ensures the entity ID corresponds to an existing record, throwing NotFoundException otherwise.


106-112: createSelectedDateTime()
Builds a DateTimeImmutable at midnight of the selected date. Consistent approach.


114-137: validateAndCheckConflicts()
Combines initial conflict checks with merged collections, verifying any weekday-specific conflicts. Thorough coverage.


139-145: getInitialConflicts()
Fetches conflicts among new availabilities themselves. Straightforward method.


147-157: getMergedCollection()
Gathers existing availabilities from the repository, merging them for broader conflict checks.


159-176: validateNewAvailabilities()
Aggregates validation results and throws AvailabilityUpdateFailed if any validations fail. Good error handling.


178-201: validateSingleAvailability()
Generates start/end times for each availability and calls validateInputs() from the collection. Good layering.


203-214: getFilteredCollection()
Filters out 'origin' or 'exclusion' items as necessary before final conflict checks. Clear naming.


216-228: findOriginId()
Locates the availability item labeled with kind='origin'. Straightforward iteration.


230-234: shouldIncludeAvailability()
Excludes exclusion or the entity with the origin ID. Concise filter.


236-248: checkExistingConflicts()
Draws on the merged collection's conflicts and aggregates them.


250-270: filterConflictsByWeekday()
Screen conflicts based on a specific weekday. Smart design to reduce false positives.


272-287: findMatchingAvailability()
Searches for a matching entity by id or tempId. Useful for correlating new and existing data.


289-312: doesConflictAffectWeekday()
Checks if the conflict occurs on a selected weekday by referencing each availability's weekday property.


314-323: updateEntities()
Updates each new entity in the repository and recalculates slots. Cohesive final step.


325-339: generateResponse()
Formats the updated collection into a JSON response with metadata. Good user feedback.


341-363: writeEntityUpdate()
Handles insert or update logic with robust checks. Throws exceptions if the entity cannot be found or updated.


365-377: writeSpontaneousEntity()
Adapts the existing entity's data to 'openinghours' if double-type logic is found. This ensures consistent entity state.

zmsadmin/routing.php (47)

18-19: New route: AvailabilityUpdateList
Creates a POST endpoint for bulk availability updates. Straightforward addition.


21-22: AvailabilityCalcSlots
Provides a POST route to compute availability slots on the fly.


27-28: AvailabilityUpdateSingle
Endpoint to update a single availability by ID.


30-31: AvailabilityConflicts
POST route for conflict checks. Great for synchronous conflict resolution.


33-34: AvailabilityListByScope
Fetches a list of availabilities for a given scope. Straightforward GET usage.


36-40: Section heading: Calldisplay
Introduces a new comment block for the Calldisplay route. No functional changes.


41-42: Calldisplay
GET endpoint for displaying call information.


44-48: Section heading: Calendar
Prepares the code block for calendar-related routes.


49-50: Calendar week route
GET endpoint for retrieving data by year/week.


53-60: Config route
Maps both GET and POST to '/config/'. Maintains flexible approach.


65-65: Named route: "mailtemplates"
Sets a clear route name for listing or handling mail templates.


67-68: MailTemplateHandler
Handles mail templates with a specific ID.


70-71: MailTemplateDeleteCustomization
Removes a customization for the specified template ID.


73-74: MailTemplateCreateCustomization
Enables creation of a customization for templates.


76-77: MailTemplateDummyPreview
Generates a preview for debugging mail templates.


79-80: MailTemplatePreviewMail
Previews the final email for a given status and scope ID.


83-90: Section heading
Introduces a block presumably associated with counters or call display. No functional difference.


102-103: Dayoff
A simple GET route listing day offs.


114-115: Department GET/POST
Handles basic department info by ID.


117-118: Department cluster
Maps cluster management under a department.


123-124: departmentAddCluster
Adds a cluster to the specified department.


126-127: departmentAddScope
Assigns a scope to a department.


150-151: Index
Reserved for the primary route '/', mapped for both GET and POST.


156-157: OIDC
Route secured with OAuth middleware for handling logins.


192-193: organisationAddDepartment
Allows expansions of an organisation with a new department.


194-195: Organisation route
Manages an organisation by ID, supporting GET and POST.


206-207: ownerAddOrganisation
Assign an organisation to an owner.


212-213: Owner route
Processes owner info by numeric ID.


215-216: Create new owner
Admin route to add an owner.


237-238: PickupHandheld
GET/POST route for handling handheld device pickups.


265-267: ProcessReserve
POST endpoint to reserve a process.


269-270: ProcessChange
POST route to modify an existing process.


271-273: ProcessQueue
Allows queue operations (GET/POST).


274-276: ProcessQueueReset
GET endpoint to reset a queue.


277-279: ProcessSave
POST route to save process data.


288-289: Profile
Maps GET/POST for user profile data.


300-302: Scope
Map for GET/POST to handle scope details.


321-322: ScopeEmergency
Handles emergencies at the scope level with flexible methods.


358-359: SourceEdit
GET/POST route for editing a source named by {name}.


376-377: UseraccountEdit
Matches user account editing by login name.


388-389: WorkstationSelect
Route to pick a workstation, supporting multiple methods.


406-407: WorkstationProcessFinished
Denotes finishing a particular workstation process.


409-410: WorkstationProcessRedirect
Redirecting the process flow across workstations.


427-428: Workstation
Generic route for workstation management or display.


453-455: ProviderHandler
Retrieves data from a given source in the provider route.


462-465: Citymap route
Links to berlin.de's city map. Possibly for external redirection or references.


478-483: Status & Healthcheck
Adds endpoints for checking application status and health.

Comment on lines +30 to +36
conflictDatesByMessage.map((item, index) => (
<div key={index} style={{ marginBottom: '1rem' }}>
{/* Convert newlines in the message to <br /> tags */}
<div dangerouslySetInnerHTML={{ __html: item.message.replace(/\n/g, '<br />') }} />
</div>
))
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Security concern with dangerouslySetInnerHTML.

Using dangerouslySetInnerHTML without proper sanitization could expose the application to XSS attacks if conflict messages contain malicious content.

Consider using a safer alternative such as:

-<div dangerouslySetInnerHTML={{ __html: item.message.replace(/\n/g, '<br />') }} />
+<div>
+  {item.message.split('\n').map((line, i) => (
+    <React.Fragment key={i}>
+      {line}
+      {i < item.message.split('\n').length - 1 && <br />}
+    </React.Fragment>
+  ))}
+</div>

Alternatively, you could use a library like DOMPurify if you need to maintain the dangerouslySetInnerHTML approach:

+import DOMPurify from 'dompurify';

-<div dangerouslySetInnerHTML={{ __html: item.message.replace(/\n/g, '<br />') }} />
+<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(item.message.replace(/\n/g, '<br />')) }} />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
conflictDatesByMessage.map((item, index) => (
<div key={index} style={{ marginBottom: '1rem' }}>
{/* Convert newlines in the message to <br /> tags */}
<div dangerouslySetInnerHTML={{ __html: item.message.replace(/\n/g, '<br />') }} />
</div>
))
);
conflictDatesByMessage.map((item, index) => (
<div key={index} style={{ marginBottom: '1rem' }}>
{/* Convert newlines in the message to <br /> tags */}
<div>
{item.message.split('\n').map((line, i) => (
<React.Fragment key={i}>
{line}
{i < item.message.split('\n').length - 1 && <br />}
</React.Fragment>
))}
</div>
</div>
))
🧰 Tools
🪛 Biome (1.9.4)

[error] 33-33: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

Comment on lines +36 to +79
switch (sortColumn) {
case 'weekday':
const aWeekDay = Object.keys(a.weekday).find(key => parseInt(a.weekday[key], 10) > 0) || '';
const bWeekDay = Object.keys(b.weekday).find(key => parseInt(b.weekday[key], 10) > 0) || '';
return multiplier * aWeekDay.localeCompare(bWeekDay);

case 'series':
const aRepeat = availabilitySeries.find(element => element.value == repeat(a.repeat))?.name || '';
const bRepeat = availabilitySeries.find(element => element.value == repeat(b.repeat))?.name || '';
return multiplier * aRepeat.localeCompare(bRepeat);

case 'startDate':
return multiplier * (a.startDate - b.startDate);

case 'endDate':
return multiplier * (a.endDate - b.endDate);

case 'time':
return multiplier * a.startTime.localeCompare(b.startTime);

case 'type':
const aType = availabilityTypes.find(element => element.value == a.type)?.name || '';
const bType = availabilityTypes.find(element => element.value == b.type)?.name || '';
return multiplier * aType.localeCompare(bType);

case 'slot':
return multiplier * (a.slotTimeInMinutes - b.slotTimeInMinutes);

case 'workstations':
const aTotal = a.workstationCount.intern + a.workstationCount.callcenter + a.workstationCount.public;
const bTotal = b.workstationCount.intern + b.workstationCount.callcenter + b.workstationCount.public;
return multiplier * (aTotal - bTotal);

case 'booking':
const aBooking = a.bookable.startInDays + a.bookable.endInDays;
const bBooking = b.bookable.startInDays + b.bookable.endInDays;
return multiplier * (aBooking - bBooking);

case 'description':
return multiplier * (a.description || '').localeCompare(b.description || '');

default:
return 0;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix switch case variable declarations

Variables declared in switch cases should be wrapped in blocks to prevent accidental access from other cases.

             switch (sortColumn) {
                 case 'weekday':
+                 {
                     const aWeekDay = Object.keys(a.weekday).find(key => parseInt(a.weekday[key], 10) > 0) || '';
                     const bWeekDay = Object.keys(b.weekday).find(key => parseInt(b.weekday[key], 10) > 0) || '';
                     return multiplier * aWeekDay.localeCompare(bWeekDay);
+                 }
                
                 case 'series':
+                 {
                     const aRepeat = availabilitySeries.find(element => element.value == repeat(a.repeat))?.name || '';
                     const bRepeat = availabilitySeries.find(element => element.value == repeat(b.repeat))?.name || '';
                     return multiplier * aRepeat.localeCompare(bRepeat);
+                 }
                
                 case 'startDate':
                     return multiplier * (a.startDate - b.startDate);
                
                 case 'endDate':
                     return multiplier * (a.endDate - b.endDate);
                
                 case 'time':
                     return multiplier * a.startTime.localeCompare(b.startTime);
                
                 case 'type':
+                 {
                     const aType = availabilityTypes.find(element => element.value == a.type)?.name || '';
                     const bType = availabilityTypes.find(element => element.value == b.type)?.name || '';
                     return multiplier * aType.localeCompare(bType);
+                 }
                
                 case 'slot':
                     return multiplier * (a.slotTimeInMinutes - b.slotTimeInMinutes);
                
                 case 'workstations':
+                 {
                     const aTotal = a.workstationCount.intern + a.workstationCount.callcenter + a.workstationCount.public;
                     const bTotal = b.workstationCount.intern + b.workstationCount.callcenter + b.workstationCount.public;
                     return multiplier * (aTotal - bTotal);
+                 }
                
                 case 'booking':
+                 {
                     const aBooking = a.bookable.startInDays + a.bookable.endInDays;
                     const bBooking = b.bookable.startInDays + b.bookable.endInDays;
                     return multiplier * (aBooking - bBooking);
+                 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
switch (sortColumn) {
case 'weekday':
const aWeekDay = Object.keys(a.weekday).find(key => parseInt(a.weekday[key], 10) > 0) || '';
const bWeekDay = Object.keys(b.weekday).find(key => parseInt(b.weekday[key], 10) > 0) || '';
return multiplier * aWeekDay.localeCompare(bWeekDay);
case 'series':
const aRepeat = availabilitySeries.find(element => element.value == repeat(a.repeat))?.name || '';
const bRepeat = availabilitySeries.find(element => element.value == repeat(b.repeat))?.name || '';
return multiplier * aRepeat.localeCompare(bRepeat);
case 'startDate':
return multiplier * (a.startDate - b.startDate);
case 'endDate':
return multiplier * (a.endDate - b.endDate);
case 'time':
return multiplier * a.startTime.localeCompare(b.startTime);
case 'type':
const aType = availabilityTypes.find(element => element.value == a.type)?.name || '';
const bType = availabilityTypes.find(element => element.value == b.type)?.name || '';
return multiplier * aType.localeCompare(bType);
case 'slot':
return multiplier * (a.slotTimeInMinutes - b.slotTimeInMinutes);
case 'workstations':
const aTotal = a.workstationCount.intern + a.workstationCount.callcenter + a.workstationCount.public;
const bTotal = b.workstationCount.intern + b.workstationCount.callcenter + b.workstationCount.public;
return multiplier * (aTotal - bTotal);
case 'booking':
const aBooking = a.bookable.startInDays + a.bookable.endInDays;
const bBooking = b.bookable.startInDays + b.bookable.endInDays;
return multiplier * (aBooking - bBooking);
case 'description':
return multiplier * (a.description || '').localeCompare(b.description || '');
default:
return 0;
}
switch (sortColumn) {
case 'weekday': {
const aWeekDay = Object.keys(a.weekday).find(key => parseInt(a.weekday[key], 10) > 0) || '';
const bWeekDay = Object.keys(b.weekday).find(key => parseInt(b.weekday[key], 10) > 0) || '';
return multiplier * aWeekDay.localeCompare(bWeekDay);
}
case 'series': {
const aRepeat = availabilitySeries.find(element => element.value == repeat(a.repeat))?.name || '';
const bRepeat = availabilitySeries.find(element => element.value == repeat(b.repeat))?.name || '';
return multiplier * aRepeat.localeCompare(bRepeat);
}
case 'startDate':
return multiplier * (a.startDate - b.startDate);
case 'endDate':
return multiplier * (a.endDate - b.endDate);
case 'time':
return multiplier * a.startTime.localeCompare(b.startTime);
case 'type': {
const aType = availabilityTypes.find(element => element.value == a.type)?.name || '';
const bType = availabilityTypes.find(element => element.value == b.type)?.name || '';
return multiplier * aType.localeCompare(bType);
}
case 'slot':
return multiplier * (a.slotTimeInMinutes - b.slotTimeInMinutes);
case 'workstations': {
const aTotal = a.workstationCount.intern + a.workstationCount.callcenter + a.workstationCount.public;
const bTotal = b.workstationCount.intern + b.workstationCount.callcenter + b.workstationCount.public;
return multiplier * (aTotal - bTotal);
}
case 'booking': {
const aBooking = a.bookable.startInDays + a.bookable.endInDays;
const bBooking = b.bookable.startInDays + b.bookable.endInDays;
return multiplier * (aBooking - bBooking);
}
case 'description':
return multiplier * (a.description || '').localeCompare(b.description || '');
default:
return 0;
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 38-38: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 39-39: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 43-43: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 44-44: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 57-57: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 58-58: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 65-65: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 66-66: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 70-70: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 71-71: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

…ening-hours-of-the-same-appointment-type-must-not-overlap
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant